Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

外部 API のレート制限に対応する

Queues を使って、外部 API のレート制限に対応する例です。

最終更新 Markdown で表示Agent セットアップ

このチュートリアルでは、Resend でメール通知を送るアプリケーションを作り、Queues で外部 API のレート制限に対応する方法を説明します。同じパターンは、任意の外部 API のレート制限に使えます。

Resend は、API 経由でアプリケーションからメールを送るサービスです。Resend のデフォルトの レート制限 は、1 秒あたり 2 リクエストです。この制限に Queues で対応します。

前提条件

  1. Cloudflare アカウント に登録します。
  2. Node.js をインストールします。

Node.js のバージョンマネージャー

権限の問題を避け、Node.js のバージョンを切り替えられるよう、Voltanvm などの Node バージョンマネージャーを使います。このガイドの後半で説明する Wrangler には、Node バージョン 16.17.0 以降が必要です。

  1. Resend に登録し、Resend のドキュメント の手順に従って API キーを生成します。

  2. あわせて、Cloudflare Queues へのアクセスも必要です。

Queues は Workers Paid プランの月額料金に含まれ、キューに対する操作に応じて課金されます。制限付きの Queues は Workers Free プランでも利用できます。詳細は 料金 を参照してください。

Queues を使う前に、Cloudflare ダッシュボード で有効にしてください。Queues を有効にするには、Workers Paid プランが必要です。

Queues を有効にする手順は次のとおりです。

  1. Cloudflare ダッシュボードで Queues ページを開きます。

    Queues を開く ↗
  2. Enable Queues を選びます。

1. 新しい Workers アプリケーションを作成する

まず、create-cloudflare CLI で Worker アプリケーションを作成します。ターミナルを開き、次のコマンドを実行します。

npm create cloudflare@latest -- resend-rate-limit-queue

セットアップでは、次のオプションを選びます。

  • What would you like to start with? では、Hello World example を選びます。
  • Which template would you like to use? では、Worker only を選びます。
  • Which language do you want to use? では、TypeScript を選びます。
  • Do you want to use git for version control? では、Yes を選びます。
  • Do you want to deploy your application? では、No を選びます(デプロイ前にいくつか変更します)。

次に、作成したディレクトリへ移動します。

cd resend-rate-limit-queue

2. Queue をセットアップする

Queue を作成し、Worker へバインディングします。次のコマンドで rate-limit-queue という名前の Queue を作成します。

Queue を作成するsh
npx wrangler queues create rate-limit-queue
Creating queue rate-limit-queue.
Created queue rate-limit-queue.

Wrangler 設定ファイル に Queue バインディングを追加する

Wrangler ファイルに次を追加します。

{
	"queues": {
		"producers": [
			{
				"binding": "EMAIL_QUEUE",
				"queue": "rate-limit-queue"
			}
		],
		"consumers": [
			{
				"queue": "rate-limit-queue",
				"max_batch_size": 2,
				"max_batch_timeout": 10,
				"max_retries": 3
			}
		]
	}
}
[[queues.producers]]
binding = "EMAIL_QUEUE"
queue = "rate-limit-queue"

[[queues.consumers]]
queue = "rate-limit-queue"
max_batch_size = 2
max_batch_timeout = 10
max_retries = 3

コンシューマーキューに max_batch_size を 2 と指定することが重要です。Resend API のデフォルトのレート制限が 1 秒あたり 2 リクエストだからです。このバッチサイズなら、キューはメッセージを 2 件ずつ処理できます。バッチサイズが 2 未満の場合、キューは次のメッセージを最大 10 秒待ちます。これ以上メッセージがなければ、そのバッチで処理します。詳細は バッチ処理、リトライ、遅延 を参照してください。

最終的な Wrangler ファイルは、次の例に近くなります。

{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "resend-rate-limit-queue",
	"main": "src/index.ts",
	// Set this to today's date
	"compatibility_date": "2026-09-20",
	"compatibility_flags": [
		"nodejs_compat"
	],
	"queues": {
		"producers": [
			{
				"binding": "EMAIL_QUEUE",
				"queue": "rate-limit-queue"
			}
		],
		"consumers": [
			{
				"queue": "rate-limit-queue",
				"max_batch_size": 2,
				"max_batch_timeout": 10,
				"max_retries": 3
			}
		]
	}
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "resend-rate-limit-queue"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-09-20"
compatibility_flags = [ "nodejs_compat" ]

[[queues.producers]]
binding = "EMAIL_QUEUE"
queue = "rate-limit-queue"

[[queues.consumers]]
queue = "rate-limit-queue"
max_batch_size = 2
max_batch_timeout = 10
max_retries = 3

3. 環境にバインディングを追加する

TypeScript がバインディングを正しく型付けできるよう、worker-configuration.d.ts の環境インターフェイスにバインディングを追加します。キューの型は Queue<Message> です。Message は次のステップで定義します。

worker-configuration.d.tsts
interface Env {
	EMAIL_QUEUE: Queue<Message>;
}

4. キューへメッセージを送る

Worker がリクエストを受け取ると、アプリケーションはキューへメッセージを送ります。簡単のため、メールアドレスをメッセージとしてキューへ送ります。新しいメッセージは 1 秒の遅延付きでキューへ送られます。

src/index.tsts
export default {
	async fetch(req, env, ctx): Promise<Response> {
		try {
			await env.EMAIL_QUEUE.send(
				{ email: await req.text() },
				{ delaySeconds: 1 },
			);
			return new Response("Success!");
		} catch (e) {
			return new Response("Error!", { status: 500 });
		}
	},
} satisfies ExportedHandler<Env>;

この処理は、任意のサブパスへのリクエストを受け付け、リクエスト本文を転送します。リクエスト本文にはメールアドレスだけが入っていることを想定しています。本番では、リクエストが POST であることを確認してください。メールのような機微情報をキューへ直接送るのも避けてください。代わりに、ユーザーを一意に識別する ID をメッセージとして送ります。コンシューマーキューがその ID でデータベースからメールアドレスを引き、メール送信に使えます。

5. キュー内のメッセージを処理する

メッセージがキューへ送られたあと、コンシューマー Worker が処理します。コンシューマー Worker はメッセージを処理し、メールを送ります。

まだ Resend を設定していないため、まずはメッセージをコンソールへ出力します。Resend を設定したあと、メール送信に使います。

次のように queue() ハンドラーを追加します。

src/index.tsts
interface Message {
	email: string;
}

export default {
	async fetch(req, env, ctx): Promise<Response> {
		try {
			await env.EMAIL_QUEUE.send(
				{ email: await req.text() },
				{ delaySeconds: 1 },
			);
			return new Response("Success!");
		} catch (e) {
			return new Response("Error!", { status: 500 });
		}
	},
	async queue(batch, env, ctx): Promise<void> {
		for (const message of batch.messages) {
			try {
				console.log(message.body.email);
				// After configuring Resend, you can send email
				message.ack();
			} catch (e) {
				console.error(e);
				message.retry({ delaySeconds: 5 });
			}
		}
	},
} satisfies ExportedHandler<Env, Message>;

上記の queue() ハンドラーは、メールアドレスをコンソールへ出力し、メールを送ります。メール送信に失敗した場合はリトライします。delaySeconds は 5 秒に設定し、短時間に連続して送らないようにします。

アプリケーションをテストするには、次のコマンドを実行します。

開発サーバーを起動するsh
npm run dev

次の cURL コマンドでアプリケーションへリクエストを送ります。

cURL リクエストでテストするsh
curl -X POST -d "test@example.com" http://localhost:8787/
[wrangler:inf] POST / 200 OK (2ms)
QueueMessage {
  attempts: 1,
  body: { email: 'test@example.com' },
  timestamp: 2024-09-12T13:48:07.236Z,
  id: '72a25ff18dd441f5acb6086b9ce87c8c'
}

6. Resend をセットアップする

Resend API を呼ぶには、Resend API キーを設定します。プロジェクトのルートに .dev.vars ファイルを作成し、次を追加します。

.dev.varstxt
RESEND_API_KEY='your-resend-api-key'

your-resend-api-key を、実際の Resend API キーに置き換えます。

次に、worker-configuration.d.tsEnv インターフェイスを更新し、RESEND_API_KEY 変数を追加します。

worker-configuration.d.tsts
interface Env {
	EMAIL_QUEUE: Queue<Message>;
	RESEND_API_KEY: string;
}

最後に、次のコマンドで resend パッケージ をインストールします。

npm i resend

これで、コード内で RESEND_API_KEY 変数を使えます。

7. Resend でメールを送る

src/index.ts で Resend パッケージをインポートし、queue() ハンドラーを更新してメールを送ります。

src/index.tsts
import { Resend } from "resend";

interface Message {
	email: string;
}

export default {
	async fetch(req, env, ctx): Promise<Response> {
		try {
			await env.EMAIL_QUEUE.send(
				{ email: await req.text() },
				{ delaySeconds: 1 },
			);
			return new Response("Success!");
		} catch (e) {
			return new Response("Error!", { status: 500 });
		}
	},
	async queue(batch, env, ctx): Promise<void> {
		// Initialize Resend
		const resend = new Resend(env.RESEND_API_KEY);
		for (const message of batch.messages) {
			try {
				console.log(message.body.email);
				// send email
				const sendEmail = await resend.emails.send({
					from: "onboarding@resend.dev",
					to: [message.body.email],
					subject: "Hello World",
					html: "<strong>Sending an email from Worker!</strong>",
				});

				// check if the email failed
				if (sendEmail.error) {
					console.error(sendEmail.error);
					message.retry({ delaySeconds: 5 });
				} else {
					// if success, ack the message
					message.ack();
				}
				message.ack();
			} catch (e) {
				console.error(e);
				message.retry({ delaySeconds: 5 });
			}
		}
	},
} satisfies ExportedHandler<Env, Message>;

queue() ハンドラーは、Resend API でメールを送ります。送信に失敗した場合はメッセージをリトライします。

最終的なスクリプトは次のとおりです。

src/index.tsts
import { Resend } from "resend";

interface Message {
	email: string;
}

export default {
	async fetch(req, env, ctx): Promise<Response> {
		try {
			await env.EMAIL_QUEUE.send(
				{ email: await req.text() },
				{ delaySeconds: 1 },
			);
			return new Response("Success!");
		} catch (e) {
			return new Response("Error!", { status: 500 });
		}
	},
	async queue(batch, env, ctx): Promise<void> {
		// Initialize Resend
		const resend = new Resend(env.RESEND_API_KEY);
		for (const message of batch.messages) {
			try {
				// send email
				const sendEmail = await resend.emails.send({
					from: "onboarding@resend.dev",
					to: [message.body.email],
					subject: "Hello World",
					html: "<strong>Sending an email from Worker!</strong>",
				});

				// check if the email failed
				if (sendEmail.error) {
					console.error(sendEmail.error);
					message.retry({ delaySeconds: 5 });
				} else {
					// if success, ack the message
					message.ack();
				}
			} catch (e) {
				console.error(e);
				message.retry({ delaySeconds: 5 });
			}
		}
	},
} satisfies ExportedHandler<Env, Message>;

アプリケーションをテストするには、次のコマンドで開発サーバーを起動します。

開発サーバーを起動するsh
npm run dev

次の cURL コマンドでアプリケーションへリクエストを送ります。

cURL リクエストでテストするsh
curl -X POST -d "delivered@resend.dev" http://localhost:8787/

Resend のダッシュボードで、指定したメールアドレスへメールが送られたことを確認できます。

8. Worker をデプロイする

Worker をデプロイするには、次のコマンドを実行します。

Worker をデプロイするsh
npx wrangler deploy

最後に、次のコマンドで Resend API キーを追加します。

Resend API キーを追加するsh
npx wrangler secret put RESEND_API_KEY

API キーの値を入力します。API キーがプロジェクトに追加されます。これで、コード内で RESEND_API_KEY 変数を使えます。

Resend API のレート制限を守りながらメールを送れる Worker を作成できました。

Worker をテストするには、次の cURL リクエストを使えます。<YOUR_WORKER_URL> を、デプロイした Worker の URL に置き換えます。

cURL リクエストでテストするbash
curl -X POST -d "delivered@resend.dev" <YOUR_WORKER_URL>

このチュートリアルの完全なコードは GitHub リポジトリ を参照してください。Hono を使っている場合は、Hono の例 を参照してください。

関連リソース

役に立ちましたか?