Open1
【BackEnd】Server側のバックグラウンド処理実装について📝

サーバー側で「バックグラウンドで処理する」ための考え方と代表的な実装方法
なぜバックグラウンド処理を分離するのか
- API 応答を速く保つ – フロントエンドや他サービスがタイムアウトしにくい
- スケールの自由度 – ワーカーだけを横に増やして重い処理をさばける
- 再試行や遅延実行が簡単 – キューに任せればリトライ・レート制限・DLQ(死活キュー)が標準で使える
主なパターン
パターン | 適したケース | メリット / 注意点 |
---|---|---|
同一プロセス内の軽量処理ctx.waitUntil() (Cloudflare Workers)/ Promise を await しない |
ログ追加・分析イベント送信などミリ秒級の処理 | すぐ書けるが、CPU を共有し再起動で失われる |
Node.js Worker Threads / child_process | CPU バウンド処理(画像変換など)を自コンテナ内で分けたい | 外部サービス不要。クラッシュ監視や水平スケールは自力 |
自前ジョブキュー(Redis/Mongo など) 例: BullMQ(Redis), Agenda(MongoDB), Bree(ファイル + Worker Threads) |
数千〜数万件/分規模、クラウドに依存したくない場合 | リポジトリ内で完結。Redis や Mongo の運用が必要 |
マネージドキュー+ワーカー Cloudflare Queues, Google Cloud Tasks, AWS SQS + Lambda, Supabase Edge Functions |
インフラ運用を極力減らしたい、オートスケールしたい | インフラはお任せ。課金体系とベンダーロックに注意 |
スケジュール/Cron 系 Agenda, Bree, Cloudflare Cron Trigger など |
毎時・毎日レポート生成、定期バッチ | 書式がシンプル。長時間ジョブはキューと併用 |
Hono(Node ランタイム)の典型的な構成例
-
エンドポイント側 (
api.ts
)const q = new Queue("patent-search", { connection: { host: "redis" } }); app.post("/search", async (c) => { const { query } = await c.req.json(); const job = await q.add("run_search", { query }); return c.json({ jobId: job.id, status: "PENDING" }); });
-
ワーカー側 (
worker.ts
)new Worker("patent-search", { connection: { host: "redis" }, concurrency: 5, processor: async (job) => { /* 検索ロジック */ } });
-
DB にステータス保存 →
/status/:jobId
でフロントがポーリングや SSE。
代表的ライブラリ/サービス早見表
目的 | 小規模・手軽 | プロダクション高負荷 | マネージド完全自動 |
---|---|---|---|
すぐ動かす |
Bree (依存ゼロ) |
BullMQ (Redis) |
Cloudflare Queues + Worker |
Cron 的処理 |
Agenda (Mongo) |
同左 | Cloudflare Cron Trigger / Cloud Scheduler |
GCP 環境 | — | Redis + BullMQ on Cloud Run | Cloud Tasks + Cloud Run |
AWS 環境 | — | Redis + BullMQ on ECS | SQS + Lambda |
選定のヒント
- 既に Redis を運用 → BullMQ が王道。UI(bull-board)も付けられる
- エッジに寄せたい/グローバル低遅延 → Cloudflare Workers + Queues
- GCP ネイティブで完結 → Cloud Tasks は IAM・HTTP 認証込みで便利
- バッチ主体で DB は Mongo → Agenda がシンプル
実装時の注意点
- 冪等性 – リトライされても二重実行にならない設計(DB に一意キー/version カラムなど)
- 監視・可視化 – 処理時間、失敗数をダッシュボード化(BullMQ UI, Cloud Logging 等)
-
シャットダウン – ワーカーは
SIGTERM
を受けたら現在のジョブを終えてから終了する
ブラウザ Service Worker との違い
Service Worker (ブラウザ) | サーバー/ワーカー | |
---|---|---|
主目的 | オフラインキャッシュ・プッシュ通知 | バックエンド非同期ジョブ |
実行場所 | ユーザー端末 | サーバー or クラウド |
トリガー | fetch, push, sync イベント | キュー投入、Cron、Webhook など |
今後の進め方(おすすめ)
- ローカル Docker Compose で Redis + BullMQ を試し、開発環境に組み込む
- 軽微なバックグラウンド作業は Cloudflare Workers 部署時に
ctx.waitUntil()
を使う - サービスが成長したら Cloudflare Queues または Cloud Tasks へ移行し、ワーカーだけを横に増やす
これで「API は即レスポンス」「重い処理は安全に並列化」という構成を段階的に取り入れられます。