このチュートリアルでは、Resend ↗ でメール通知を送るアプリケーションを作り、Queues で外部 API のレート制限に対応する方法を説明します。同じパターンは、任意の外部 API のレート制限に使えます。
Resend は、API 経由でアプリケーションからメールを送るサービスです。Resend のデフォルトの レート制限 ↗ は、1 秒あたり 2 リクエストです。この制限に Queues で対応します。
- Cloudflare アカウント ↗ に登録します。
Node.js↗ をインストールします。
Node.js のバージョンマネージャー
権限の問題を避け、Node.js のバージョンを切り替えられるよう、Volta ↗ や nvm ↗ などの Node バージョンマネージャーを使います。このガイドの後半で説明する Wrangler には、Node バージョン 16.17.0 以降が必要です。
-
Resend ↗ に登録し、Resend のドキュメント ↗ の手順に従って API キーを生成します。
-
あわせて、Cloudflare Queues へのアクセスも必要です。
Queues は Workers Paid プランの月額料金に含まれ、キューに対する操作に応じて課金されます。制限付きの Queues は Workers Free プランでも利用できます。詳細は 料金 を参照してください。
Queues を使う前に、Cloudflare ダッシュボード ↗ で有効にしてください。Queues を有効にするには、Workers Paid プランが必要です。
Queues を有効にする手順は次のとおりです。
-
Cloudflare ダッシュボードで Queues ページを開きます。
Queues を開く ↗ -
Enable Queues を選びます。
まず、create-cloudflare CLI ↗ で Worker アプリケーションを作成します。ターミナルを開き、次のコマンドを実行します。
npm create cloudflare@latest -- resend-rate-limit-queueyarn create cloudflare resend-rate-limit-queuepnpm 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-queueQueue を作成し、Worker へバインディングします。次のコマンドで rate-limit-queue という名前の Queue を作成します。
npx wrangler queues create rate-limit-queueCreating 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 = 3TypeScript がバインディングを正しく型付けできるよう、worker-configuration.d.ts の環境インターフェイスにバインディングを追加します。キューの型は Queue<Message> です。Message は次のステップで定義します。
interface Env {
EMAIL_QUEUE: Queue<Message>;
}Worker がリクエストを受け取ると、アプリケーションはキューへメッセージを送ります。簡単のため、メールアドレスをメッセージとしてキューへ送ります。新しいメッセージは 1 秒の遅延付きでキューへ送られます。
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 でデータベースからメールアドレスを引き、メール送信に使えます。
メッセージがキューへ送られたあと、コンシューマー Worker が処理します。コンシューマー Worker はメッセージを処理し、メールを送ります。
まだ Resend を設定していないため、まずはメッセージをコンソールへ出力します。Resend を設定したあと、メール送信に使います。
次のように queue() ハンドラーを追加します。
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 秒に設定し、短時間に連続して送らないようにします。
アプリケーションをテストするには、次のコマンドを実行します。
npm run dev次の cURL コマンドでアプリケーションへリクエストを送ります。
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'
}Resend API を呼ぶには、Resend API キーを設定します。プロジェクトのルートに .dev.vars ファイルを作成し、次を追加します。
RESEND_API_KEY='your-resend-api-key'your-resend-api-key を、実際の Resend API キーに置き換えます。
次に、worker-configuration.d.ts の Env インターフェイスを更新し、RESEND_API_KEY 変数を追加します。
interface Env {
EMAIL_QUEUE: Queue<Message>;
RESEND_API_KEY: string;
}最後に、次のコマンドで resend パッケージ ↗ をインストールします。
npm i resendyarn add resendpnpm add resendbun add resendこれで、コード内で RESEND_API_KEY 変数を使えます。
src/index.ts で Resend パッケージをインポートし、queue() ハンドラーを更新してメールを送ります。
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 でメールを送ります。送信に失敗した場合はメッセージをリトライします。
最終的なスクリプトは次のとおりです。
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>;アプリケーションをテストするには、次のコマンドで開発サーバーを起動します。
npm run dev次の cURL コマンドでアプリケーションへリクエストを送ります。
curl -X POST -d "delivered@resend.dev" http://localhost:8787/Resend のダッシュボードで、指定したメールアドレスへメールが送られたことを確認できます。
Worker をデプロイするには、次のコマンドを実行します。
npx wrangler deploy最後に、次のコマンドで Resend API キーを追加します。
npx wrangler secret put RESEND_API_KEYAPI キーの値を入力します。API キーがプロジェクトに追加されます。これで、コード内で RESEND_API_KEY 変数を使えます。
Resend API のレート制限を守りながらメールを送れる Worker を作成できました。
Worker をテストするには、次の cURL リクエストを使えます。<YOUR_WORKER_URL> を、デプロイした Worker の URL に置き換えます。
curl -X POST -d "delivered@resend.dev" <YOUR_WORKER_URL>このチュートリアルの完全なコードは GitHub リポジトリ ↗ を参照してください。Hono ↗ を使っている場合は、Hono の例 ↗ を参照してください。