+ 作るログイン
1 / 14
Cloudflare のすべて ― 1機能ずつ、仕組みと存在理由から / 全35本

Cloudflare 24:Queues ― 重い仕事を預けて、すぐ返す

発行
アニメモ公式
版
第2版
改訂
コマ
全14

Cloudflare Queues を、なぜ必要かから説明します。送り手と受け手、束(バッチ)での受け取り、再挑戦とデッドレターキュー、送り手と受け手を切り離す価値、wrangler での設定とコード、料金と制限、2回届く・順番が保証されないといった落とし穴まで。

時間のかかる仕事を、利用者に待たせている

会員登録のボタンを押したとします。サーバーは、利用者をデータベースに登録し、ようこそメールを送り、画面に「登録しました」と返します。

このうち、メールの送信は、外のメール配信サービスに頼む仕事です。相手が混んでいれば数秒かかりますし、落ちていれば失敗します。これをリクエストの中でやると、次のようなことが起きます。

困りごと中身
待たされるメールを送り終えるまで、利用者の画面が固まる
巻き添えで失敗するメールの失敗で、登録そのものが失敗したように見える
やり直せない送れなかったメールを、誰も後で送り直さない
集中に弱い一度に大量の登録が来ると、外のサービスの上限に当たる

メールのほかにも、画像の縮小、PDF の作成、外部 API への通知、ログの集計など、「今すぐでなくてよいが、確実にやってほしい仕事」はたくさんあります。

これを利用者のリクエストから切り離すのが、キューという仕組みです。Cloudflare では、それを Queues として Workers から使えます。

※この号の内容は2026年9月時点の情報です。料金・上限・提供状況は変わることがあるので、使う前に必ず公式のドキュメントで確かめてください。

  • Cloudflare のすべて 24 ― Queues
  • 1 / 14
  • 時間のかかる仕事を、利用者に待たせている
  • 返事まで数秒…
  • 利用者
  • 送り手 Worker
  • 外のサービス
  • 受け付けて、すぐ返す
  • 登録ボタン → ようこそメールを送り終えるまで画面が固まる
  • 送り先が落ちていたら? 失敗したら? 利用者の操作まで巻き添えになる
  • メール送信や画像変換を、リクエストの中でやると遅い。

間に「キュー」を置き、仕事を預ける

キュー(待ち行列)は、仕事のメモを貯めておく場所です。このメモをメッセージと呼びます。

使い方は、銀行の窓口の整理券に似ています。窓口(送り手)は、用件を聞いて整理券を渡したら、すぐ次の人に対応できます。奥の係(受け手)が、整理券を順に片づけていきます。

役英語仕事
送り手producerメッセージをキューに預け、利用者にはすぐ返事をする
キューqueueメッセージを、受け手が取りに来るまで確実に保管する
受け手consumerメッセージを受け取り、実際の仕事をする

図の中で、送り手の Worker は、メッセージをキューに入れた時点で利用者に「受け付けました」と返します。メールが実際に届くのは数秒後かもしれませんが、利用者はもう次の操作に進めます。

Cloudflare Queues の特徴は、送り手も受け手も Worker で書けることです。サーバーを用意したり、キューのソフトウェアを運用したりする必要はありません。キューは「必ず届ける」ことを保証する仕組みを、Cloudflare の側が持っています。

  • Cloudflare のすべて 24 ― Queues
  • 2 / 14
  • 間に「キュー」を置き、仕事を預ける
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手 Worker
  • 受け付けて、すぐ返す
  • 外のサービス(メール送信など)
  • キュー=仕事のメモ(メッセージ)を貯めておく待ち行列
  • 預けた時点で利用者には「受け付けました」と返せる
  • 送り手は預けたらすぐ返す。受け手が後で順に片づける。

送り手:send() で1行、預けるだけ

送り手の Worker は、バインディング(23号で見たのと同じ仕組み)でキューを受け取り、send() を呼ぶだけです。

ts
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const user = await registerUser(request, env);

    // メール送信は預けるだけ。ここでは待たない
    await env.JOBS.send({ type: "welcome-mail", to: user.email, userId: user.id });

    return Response.json({ ok: true });
  },
};

send() が待つのは「キューが確かに受け取った」までです。メールの送信そのものは待ちません。だから、応答はすぐ返ります。

メッセージの中身には、JSON にできる値(文字列・数値・オブジェクト・配列など)を入れられます。

メソッド・指定用途
send(body)1通を預ける
sendBatch([...])何通かをまとめて預ける
delaySecondsすぐではなく、指定した秒数の後に届ける

預けた後、送り手はそのメッセージにもう関わりません。うまく処理されたか、失敗したかは、受け手とキューの間の話になります。

  • Cloudflare のすべて 24 ― Queues
  • 3 / 14
  • 送り手:send() で1行、預けるだけ
  • env.JOBS.send({
  • to: user.email })
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手 Worker
  • 受け付けて、すぐ返す
  • 外のサービス(メール送信など)
  • 送り手(producer)はバインディングの send() を呼ぶだけ。待つのは預ける時間だけ
  • まとめて預けるなら sendBatch()。後で届けたいなら delaySeconds
  • 中身は JSON にできる値。預けた後は、送り手はもう関わらない。

受け手:まとめて受け取り、まとめて片づける

受け手の Worker には、fetch() の代わりに(または並べて)queue() というハンドラを書きます。Cloudflare は、キューに貯まったメッセージを束(バッチ)にして、この queue() を呼び出します。

なぜ1通ずつではなく束なのでしょうか。1通ごとに Worker を起動するより、何通かをまとめて処理したほうが効率がよいからです。たとえば、ログを100件まとめてデータベースに1回で書き込めば、100回書くよりずっと速く、安くなります。

束の区切り方は、2つの設定で決まります。

設定意味
max_batch_size1つの束に入れる最大の件数
max_batch_timeout束がいっぱいにならなくても、この秒数を待ったら送る

「件数がいっぱいになる」か「時間が来る」かの、早いほうで束が送られます。メッセージが少ない時間帯でも、待たされすぎることはありません。

受け手は、束の中のメッセージを1件ずつ処理し、うまくいったものに ack()(受け取り済み)を付けます。ack されたメッセージは、キューから消えます。

  • Cloudflare のすべて 24 ― Queues
  • 4 / 14
  • 受け手:まとめて受け取り、まとめて片づける
  • 束で届く
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手 Worker
  • 受け付けて、すぐ返す
  • 外のサービス(メール送信など)
  • 束は「最大○件」か「最大○秒待った」の早いほうで区切られる
  • 受け手(consumer)は queue() ハンドラで束を受け取り、1件ずつ ack する
  • 1通ずつではなく、束(バッチ)で受け取る。数と待ち時間で決める。

失敗したら、キューに戻ってやり直す

受け手が仕事に失敗することはよくあります。メール配信サービスが一時的に落ちている、外部 API が混んでいて断られた、などです。

キューの大事な仕事は、こうした一時的な失敗で仕事を失わないことです。受け手がメッセージの処理に失敗すると、そのメッセージはキューに戻され、後でもう一度届けられます。

戻し方は2通りあります。

方法どうなるか
msg.retry() を呼ぶそのメッセージだけが、キューに戻る
queue() の中で例外が出るack していないメッセージが、束ごと戻る

retry({ delaySeconds: 60 }) のように、次に届けるまでの待ち時間を指定できます。相手が混んでいるときにすぐ再挑戦しても、また断られるだけです。少し間を空けたほうが、成功しやすくなります。

再挑戦の回数には上限があり、max_retries で決めます。既定では数回です。上限を超えても失敗したメッセージがどうなるかは、次のページで見ます。

  • Cloudflare のすべて 24 ― Queues
  • 5 / 14
  • 失敗したら、キューに戻ってやり直す
  • retry():少し待って再挑戦
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手 Worker
  • 受け付けて、すぐ返す
  • 外のサービス(メール送信など)
  • 例外を投げる・retry() を呼ぶと、そのメッセージはキューに戻る
  • 再挑戦の回数(max_retries)と、次までの待ち時間を決められる
  • 外のサービスが一時的に落ちていても、仕事は消えない。

何度やってもダメなら、DLQ に隔離する

何度再挑戦しても失敗するメッセージがあります。メールアドレスの形式が壊れている、参照している利用者がもう削除されている、受け手のコードにバグがある、などです。これらは、何回やり直しても成功しません。

こうしたメッセージを置いておく場所が、デッドレターキュー(DLQ)です。max_retries を使い切ったメッセージは、設定しておいた DLQ に移されます。

DLQ が無いと、回数を使い切ったメッセージはそのまま消えます。何が失敗したのか、あとから調べる手がかりが残りません。

DLQ も、ふつうのキューと同じものです。だから、DLQ にも受け手を付けられます。

DLQ の使い方例
調べる管理画面や wrangler で中身を確かめ、失敗の原因を探す
知らせるDLQ の受け手で、開発者にチャットで通知する
直してから戻すバグを直した後、DLQ のメッセージを元のキューに入れ直す

キューを作るときは、DLQ もいっしょに作る習慣にしておきましょう。

  • Cloudflare のすべて 24 ― Queues
  • 6 / 14
  • 何度やってもダメなら、DLQ に隔離する
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手 Worker
  • 受け付けて、すぐ返す
  • DLQ(失敗の置き場)
  • 外のサービス(メール送信など)
  • DLQ(デッドレターキュー)=回数を使い切ったメッセージの置き場
  • 設定しないと、使い切ったメッセージは消える。原因を調べられなくなる
  • 失敗し続けるメッセージを、別のキューに退避して後で調べる。

受け手が止まっても、受け付けは止まらない

ここまで見てきたことを、少し引いて眺めてみます。キューのいちばんの価値は、送り手と受け手を切り離すことです。

図では、受け手の Worker が止まっています。外のメール配信サービスが落ちたのかもしれませんし、受け手のコードに不具合があってデプロイし直している最中かもしれません。それでも、送り手は何も困りません。メッセージはキューに貯まっていき、利用者には「受け付けました」と返し続けます。受け手が直れば、貯まった分から順に処理されます。

この切り離しは、アクセスの急な増加にも効きます。

場面キューが無いとキューがあると
受け手が落ちた登録そのものが失敗する貯まるだけ。後で処理される
急なアクセス増外のサービスの上限に当たる受け手が自分のペースで片づける
受け手を直す直している間は受け付けられない受け付けは続けたまま直せる

ただし、キューの保持期間には限りがあります。何日も止めたままにすると、古いメッセージから消えていきます(料金と制限のページ)。

  • Cloudflare のすべて 24 ― Queues
  • 7 / 14
  • 受け手が止まっても、受け付けは止まらない
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手(停止中)
  • 受け付けて、すぐ返す
  • 外のサービス(メール送信など)
  • 受け手や外のサービスが落ちている間も、仕事はキューに貯まる
  • 直ったら、貯まった分から順に処理される。急なアクセス増もならせる
  • 送り手と受け手を切り離す。これがキューの一番の価値。

導入:キューを作り、両側に書く

Queues を使い始める手順は、次のとおりです。

順番やることコマンドや場所
1キューを作るnpx wrangler queues create emails
2DLQ 用のキューも作るnpx wrangler queues create emails-dlq
3送り手の設定に producers を書くwrangler.jsonc
4受け手の設定に consumers を書き、queue() を実装するwrangler.jsonc とコード
5デプロイするnpx wrangler deploy

設定は、たとえば次のようになります。送り手と受け手が同じ Worker なら、1つのファイルに両方を書きます。

jsonc
{
  "queues": {
    "producers": [{ "binding": "JOBS", "queue": "emails" }],
    "consumers": [{ "queue": "emails", "dead_letter_queue": "emails-dlq" }]
  }
}

binding に書いた名前(ここでは JOBS)が、送り手のコードの env.JOBS になります。

Queues は、以前は有料プラン専用でしたが、2026年2月から Workers の無料プランでも使えるようになりました。まず無料で試せます。

Worker の外から取りに行く「HTTP の受け手(pull consumer)」も作れます。Cloudflare の外のサーバーでメッセージを処理したいときに使います。

  • Cloudflare のすべて 24 ― Queues
  • 8 / 14
  • 導入:キューを作り、両側に書く
  • キューを作る
  • 送り手に書く
  • 受け手に書く
  • デプロイ
  • queues create
  • キュー本体と、DLQ 用のキューを作る
  • producers
  • binding の名前で send() できるようにする
  • consumers
  • 束の大きさ・再挑戦・DLQ を決める
  • 送り手と受け手は同じ Worker でも、別々の Worker でもよい
  • 送り手には producers、受け手には consumers を設定する。

使い方:queue() で束を受け取り、ack する

受け手のコードは、次のようになります。

ts
type Job = { type: "welcome-mail"; to: string; userId: string };

export default {
  async queue(batch: MessageBatch<Job>, env: Env): Promise<void> {
    for (const msg of batch.messages) {
      try {
        await sendMail(msg.body, env);
        msg.ack(); // 済み。キューから消える
      } catch (err) {
        console.error("送信に失敗", msg.id, err);
        msg.retry({ delaySeconds: 60 }); // 1分後にもう一度
      }
    }
  },
};

ポイントは、1件ずつ ack か retry かを決めることです。

書き方結果
1件ずつ ack()/retry()成功した分だけ消え、失敗した分だけ戻る
何も呼ばずに正常に終わる束の全部が成功したとみなされる
途中で例外が出るack していない分が、束ごと戻る

束ごと戻すと、成功していたメッセージまでもう一度処理されます。メールなら二重送信です。1件ずつ決める書き方にしておくと、こうした巻き添えが起きません。

msg.id はメッセージごとの ID、msg.attempts は何回目の挑戦かです。ログに出しておくと、失敗を調べるときに役立ちます。

  • Cloudflare のすべて 24 ― Queues
  • 9 / 14
  • 使い方:queue() で束を受け取り、ack する
  • async queue(batch, env) {
  • ack()
  • 済み。消す
  • for (const msg of batch.messages) {
  • try { await sendMail(msg.body);
  • retry()
  • 後でもう一度
  • msg.ack(); }
  • catch { msg.retry({ delaySeconds: 60 }); }
  • 何もしない
  • 束ごと成功
  • }
  • 例外
  • 束ごと再挑戦
  • }
  • 1件ずつ ack/retry を決めると、成功した分だけ消える。

設定:束の大きさ・再挑戦・DLQ

受け手の設定(consumers)で、キューのふるまいを調整できます。

jsonc
"consumers": [{
  "queue": "emails",
  "max_batch_size": 10,        // 1束の最大件数
  "max_batch_timeout": 5,      // 束がそろうまで待つ最大の秒数
  "max_retries": 3,            // 再挑戦の回数
  "dead_letter_queue": "emails-dlq",
  "max_concurrency": 5         // 同時に動く受け手の数の上限
}]
設定大きくすると小さくすると
max_batch_sizeまとめて効率よく処理できる1件あたりの待ち時間が短くなる
max_batch_timeout束が大きくなりやすい届くまでの遅れが小さくなる
max_retries一時的な障害に粘り強くなる壊れたメッセージを早く DLQ に送れる
max_concurrency貯まった分を速く片づける外のサービスに優しい

どれも既定値があるので、書かなくても動きます。ただし DLQ は既定では無いので、必ず自分で指定してください。

外のサービスに「1秒に何回まで」という上限がある場合は、max_concurrency と max_batch_size を小さめにして、受け手の速さを抑えます。

  • Cloudflare のすべて 24 ― Queues
  • 10 / 14
  • 設定:束の大きさ・再挑戦・DLQ
  • "consumers": [{
  • "queue": "emails",
  • max_batch_size
  • 1束の最大件数
  • "max_batch_size": 10,
  • "max_batch_timeout": 5,
  • max_batch_timeout
  • 束を待つ秒数
  • "max_retries": 3,
  • "dead_letter_queue": "emails-dlq"
  • max_retries
  • 再挑戦の回数
  • }]
  • dead_letter_queue
  • 行き先のキュー
  • 既定値のままでも動くが、DLQ だけは必ず決めておく。

料金と制限:操作の回数で数える

Queues の料金は、キューに対する操作の回数で数えます。操作とは「書く・読む・消す」のことで、メッセージ 64KB ごとに1回と数えます。

ふつうの小さなメッセージ1通は、「送り手が書く・受け手が読む・ack で消す」で、およそ3回の操作になります。再挑戦すると、そのたびに「読む」が1回増えます。

項目Workers 無料プランWorkers 有料プラン
操作の回数1日 1万回まで月の込みの回数を超えた分が従量
メッセージの保持最長24時間設定で最長14日まで
機能有料プランと同じ機能が使える同左

1通のメッセージの大きさにも上限があります。画像や大きな JSON をそのまま入れず、中身は R2(22号)に置いて、メッセージにはそのキーだけを入れます。1日に1万回というと、およそ3,000通強です。試作には十分ですが、本番ではすぐに届く量なので、有料プランを考えましょう。

保持期間を過ぎたメッセージは、処理されないまま消えます。受け手を長く止めておかないようにしてください。

※2026年9月時点の情報です。料金・上限は変わるので、公式の Pricing と Limits のページで確かめてください。

  • Cloudflare のすべて 24 ― Queues
  • 11 / 14
  • 料金と制限:操作の回数で数える
  • 数え方
  • 書く・読む・消すの操作。64KB ごとに1回
  • 無料プラン
  • 1日 1万回まで。保持は最長24時間
  • 有料プラン
  • 月の込みの回数を超えた分が従量
  • 再挑戦
  • やり直すたびに「読む」が増える
  • 1通の大きさ
  • 上限あり。大きな中身は R2 に置く
  • 保持期間を過ぎたメッセージは消える。受け手を長く止めたままにしない
  • 2026年9月時点。料金・上限は変わるので公式の Pricing / Limits で確かめる
  • 1通は「書く・読む・消す」でおよそ3回。無料枠あり。

よくある落とし穴

キューを使うと、「ふつうの関数呼び出し」とは違う性質に出会います。

落とし穴何が起きるかどうするか
1回だけ届くと思うQueues は「少なくとも1回」届ける。まれに同じメッセージが2回届く2回処理しても結果が同じになる作り(冪等)にする
順番に頼る届く順番は保証されない順番が大事なら Durable Objects(21号)で並べる
DLQ が無い失敗し続けたメッセージが黙って消えるDLQ を必ず作る
大きな中身1通の大きさの上限に当たるR2 に置いてキーだけ送る
束ごと例外成功した分まで再処理される1件ずつ ack/retry する

いちばん大事なのは1つめの冪等(べきとう)です。同じメッセージが2回届いたときに、メールが2通届いたり、ポイントが2回付いたりしてはいけません。

よくある対策は、メッセージに一意の IDを入れておき、受け手が処理する前に「この ID はもう処理したか」を D1(23号)や KV(20号)で確かめる方法です。処理が済んだら、その ID を記録します。

  • Cloudflare のすべて 24 ― Queues
  • 12 / 14
  • よくある落とし穴
  • 「必ず1回だけ」と思い込む → 少なくとも1回。2回届いても困らない作りに
  • 届く順番に頼る → 順番は保証されない。順番が要るなら Durable Objects(21号)
  • DLQ を設定しない → 失敗し続けたメッセージが黙って消える
  • 画像そのものを入れる → 大きさの上限。R2 に置いてキーだけ送る
  • メッセージに ID を入れ、処理済みかを D1 や KV で確かめる
  • 2回届くことがある。順番は保証されない。中身は小さく。

他の号とのつながり

Queues は、ほかの機能と機能の間をつなぐベルトコンベアのような役目をします。

号機能Queues との関係
18Workers送り手も受け手も Worker で書く
20 / 23KV・D1処理済みの ID を記録して、二重処理を防ぐ
21Durable Objects順番が大事な処理を任せる
22R2大きな中身の置き場。ファイルが置かれたらキューに知らせることもできる
25Workflows何段にも分かれ、途中で待つ処理を任せる
32分析とログ失敗や DLQ に貯まった件数を見張る

特に Workflows(25号)との使い分けは、よく迷うところです。「メールを1通送る」「画像を1枚縮める」のように、1回で終わる仕事をたくさんさばくなら Queues が向いています。「支払いを確かめ、在庫を押さえ、3日後にリマインドを送る」のように、何段にも分かれ、途中で待ったり、前の段の結果を使ったりする仕事なら Workflows が向いています。

  • Cloudflare のすべて 24 ― Queues
  • 13 / 14
  • 他の号とのつながり
  • 18 Workers
  • 22 R2
  • 23 D1
  • 送り手と受け手
  • 中身の置き場・通知
  • 処理済みの記録
  • 25 Workflows
  • 21 Durable Objects
  • 32 分析とログ
  • 何段もある処理
  • 順番が要るとき
  • 失敗を見つける
  • 1回で終わる「後でやればよい仕事」は Queues、何段もあるなら Workflows
  • R2 にファイルが置かれたら、キューに知らせを入れる(イベント通知)こともできる
  • Queues は、ほかの機能をつなぐ「ベルトコンベア」。

まとめ:預けて、すぐ返す

この号で見たことをまとめます。

項目内容
なぜ要るのか遅い仕事・落ちるかもしれない仕事で、利用者を待たせないため
仕組み送り手が預け、キューが保管し、受け手が後で片づける
送り手env.JOBS.send()。預けたらすぐ返す
受け手queue() で束を受け取り、1件ずつ ack()/retry()
失敗キューに戻って再挑戦。使い切ったら DLQ へ
一番の価値送り手と受け手を切り離す。受け手が止まっても受け付けは続く
料金操作の回数。無料プランでも1日1万回まで使える
注意少なくとも1回届く(冪等に)。順番は保証されない

次の25号では、何段にも分かれた処理を確実に最後までやり遂げる Workflows と、決まった時刻に Worker を動かす Cron Triggers を見ます。

  • Cloudflare のすべて 24 ― Queues
  • 14 / 14
  • まとめ:預けて、すぐ返す
  • キュー
  • 利用者
  • 送り手 Worker
  • 受け手 Worker
  • 受け付けて、すぐ返す
  • DLQ(失敗の置き場)
  • 外のサービス(メール送信など)
  • 遅い仕事・落ちるかもしれない仕事を、リクエストから切り離す
  • 2回届いても困らない作り(冪等)にしておく。これだけは忘れない
  • send で預け、queue で束を片づけ、失敗は DLQ へ。

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]