daemons について
Vercel Daemons は、キューコンシューマーやワーカーなど、継続的にジョブを取得する長時間稼働のコンテナプロセスです。このスキルでは、Vercel アプリと並行してバックグラウンド処理を運用するチーム向けに、設定、デプロイのライフサイクル、スケーリング、終了処理、制限を説明します。
主な機能
- 01コンテナベースのバックグラウンドプロセスを実行
- 02リージョンごとのインスタンス設定
- 03終了またはクラッシュしたインスタンスを再起動
- 04プロセス出力をプロジェクトのログに転送
- 05スケーリングとグレースフルシャットダウンの説明
- 06ベータ版の制限と非対応モードを記載
活用シーン
- 01常時稼働するキューコンシューマーの実行
- 02Vercel アプリと並行したワーカーのデプロイ
- 03リージョン別のデーモンインスタンス設定
- 04安全なロールアウトとジョブ再試行の計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel/ vercel-plugin --skill daemonsインストール後、Claude Code で/daemonsを入力して読み込まれたか確認します。
詳細
Vercel Daemons
Vercel Daemons は、アプリと同じプロジェクト内でコンテナイメージから実行される、長時間稼働するバックグラウンドプロセスに関するエキスパートです。
Daemons はすべてのプランでパブリックベータです。推奨する際は、その旨を伝えてください。
概要
daemon は、指定した各リージョンで、1つのコンテナイメージから同一のインスタンスを固定数実行する、プロジェクト内の名前付きリソースです。Vercel は daemon の Dockerfile または Containerfile からイメージをビルドし、デプロイが本番デプロイになるとロールアウトします。終了またはクラッシュしたインスタンスは再起動され、stdout/stderr はプロジェクトの Logs に転送されます。Daemons は Fluid compute 上で実行されます。
Daemons はインバウンドトラフィックを受信できません。キュー、ワークフローエンジン、または外部 API から作業を取得します。
Daemons を使用する場面
継続的なループを持ち、作業を取得するプロセスには daemon を使用してください。
| 必要なもの | 使用するもの | 理由 |
|---|---|---|
| 常時稼働するキューコンシューマー(Vercel Queues のポーリングモード、SQS、Kafka、Redis)、Celery/Sidekiq/BullMQ ワーカー、ワークフローエンジンのワーカー、セルフホストの CI ランナー | Daemons | 長時間稼働するループで、リージョンごとに固定数のインスタンスがあり、リクエストが不要 |
| HTTP API、Webhook、ストリーミング、WebSocket | Vercel Functions(⤳ skill: vercel-functions) | Daemons はトラフィックを受信できない |
| ファイア・アンド・フォーゲットのバックグラウンドジョブ、ファンアウト、Vercel がハンドラーを呼び出すバッファリング | Vercel Queues のプッシュモード(⤳ skill: queues) | サーバーレスで自動的にスケールし、プレビューでも動作 |
| スリープ、フック、承認を伴う永続的な複数ステップのロジック | Vercel Workflows(⤳ skill: workflow) | 永続的なステップと再生 |
| スケジュールに基づいたコードの実行 | Cron Jobs(⤳ skill: vercel-functions) | 時間ベースのトリガー |
| 信頼できないコードや AI 生成コードの隔離実行 | Vercel Sandbox(⤳ skill: vercel-sandbox) | エフェメラルな microVM |
| 1つのプロジェクト内の複数のフロントエンドとバックエンド | Vercel Services(⤳ skill: vercel-services) | Daemons は Services の隣で動作し、Services そのものではない |
ユーザーの作業がリクエスト駆動型の場合は、Functions または Queues のプッシュモードを優先してください。常時稼働させる必要がある場合にのみ daemon を選択してください。
クイックスタート
ワーカーのソースディレクトリに Dockerfile を追加します。
# worker/Dockerfile
FROM node:24-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "worker.js"]
トップレベルの daemons キーの下で daemon を宣言します。
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"daemons": {
"worker": {
"root": "worker/",
"entrypoint": "Dockerfile",
"instances": { "iad1": 2 }
}
}
}
同じ設定は、vercel.toml の [daemons.worker] テーブルでも使用できます。本番環境にデプロイしてください。Vercel はイメージをビルドし、daemon.worker として Vercel Container Registry にプッシュしてから、iad1 で2つのインスタンスを起動します。
Daemons は常にトップレベルで宣言し、services の中には配置しません。既存のアプリ(Next.js、Services、その他)と並行して実行され、Vercel のビルド方法は変わりません。
設定リファレンス
| フィールド | 型 | 必須 | 備考 |
|---|---|---|---|
root | string | はい | vercel.json からの相対パスで指定するソースディレクトリです。プロジェクトの範囲内に収める必要があります。このディレクトリ内のファイルは静的アセットとして公開されません |
entrypoint | string | はい | root からの相対パスで指定する Dockerfile または Containerfile のパスです。そのディレクトリがビルドコンテキストになります |
instances | Record<region, number> | はい | リージョン ID ごとのインスタンス数で、それぞれ 0~100 です。Vercel は指定されたリージョンでのみ実行します |
command | string[] | いいえ | イメージの ENTRYPOINT と CMD を置き換えます。シェル経由では実行されません |
resources | { requests: { memory } } | いいえ | 1Gi(1 vCPU)、2Gi(1 vCPU、デフォルト)、4Gi(2 vCPU)、8Gi(4 vCPU) |
instancesとreplicasの違い:公開されているvercel.jsonスキーマと Build Output API ではinstancesを使用します。replicasは非推奨のエイリアスで、instancesが設定されている場合は無視されます。プロジェクトですでにreplicasを使用している場合はそのまま動作させ、新しい設定ではinstancesを記述してください。- 名前:小文字のみを使用し、
_、__、または1つ以上の-で連結します(worker、email_sender、celery-beatは使用できますが、Worker、worker1、_workerは使用できません)。最大64文字です。連続するハイフンが統合された後に同じイメージリポジトリ名になる2つの名前(例:a-bとa--b)を使用すると、ビルドは失敗します。デーモンとサービスで同じ名前を使用できます。 - 拒否されるフィールド:
framework、runtime、buildCommand、bindingsなどのサービス用フィールドをデーモンに設定すると、検証に失敗します。 - ビルド:イメージは Linux
amd64向けにビルドされます。デプロイ環境変数は、ビルド引数としてイメージのビルドに渡されます。 - シェル機能:
commandは exec 形式です。変数を展開するには、["sh", "-c", "exec node worker.js --id $WORKER_ID"]を使用してください。 CMDがない場合:イメージにENTRYPOINTもCMDも設定されておらず、commandも指定されていない場合、ビルドは失敗します。
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"daemons": {
"celery": {
"root": "backend/",
"entrypoint": "Dockerfile",
"command": ["celery", "-A", "app", "worker", "--loglevel=info"],
"instances": { "iad1": 2, "cdg1": 1 },
"resources": { "requests": { "memory": "4Gi" } }
}
}
}
ライフサイクルとスケーリング
- ベータ期間中は本番環境のみです。 デーモンは本番デプロイでのみ実行されます。プレビューデプロイではデーモンは起動しません。イメージをローカルで実行して変更をテストしてください。
- ロールアウト:デプロイが本番環境になると(デプロイ、昇格、Instant Rollback、またはローリングリリースの完了時)、Vercel は新しいインスタンスを起動し、以前のデプロイのインスタンスに
SIGTERMを送信します。短時間は両方のバージョンが同時に実行されるため、どちらも同じキューを処理でき、同じデータベーススキーマに対応できる必要があります。 - イメージ、コマンド、環境変数はデプロイに紐づきます。これらを変更するには、新たに本番デプロイしてください。
vercel.jsonによるスケーリング:instancesを変更して本番環境にデプロイします。このマップは以前の設定を置き換え、削除されたリージョンは停止します。- スケーリングのオーバーライド:プロジェクトダッシュボードで、Daemons → デーモンを選択 → Set Scaling Overrides の順に操作します。オーバーライドはデプロイ後も保持され、Clear scaling overrides で解除するまで
instancesより優先されます。instancesのvercel.jsonでの変更が反映されないように見える場合は、まずオーバーライドを確認してください。オートスケーリングはなく、CLI や API からのスケーリングもまだ利用できません。 - 削除せずに停止する:すべてのリージョンを
0にするか、instancesを{}にするか、ダッシュボードから0のオーバーライドを設定します。 - 削除:
daemonsからデーモンを削除し、本番環境にデプロイします。 - 一時停止中のプロジェクトでは、すべてのデーモンインスタンスが停止します。プロジェクトを再開すると、再び起動します。
グレースフルシャットダウン
Vercel はロールアウト、スケールダウン、削除、手動再起動の際に SIGTERM を送信し、その後、デフォルトで10秒間待機してからプロセスを終了します。新しい作業の受付を直ちに停止し、進行中のジョブを完了させてください。インスタンスはいつでも停止する可能性があるため、ジョブは冪等で再試行しても安全でなければなりません。キューメッセージは処理が完了してから確認してください。
// worker/worker.ts
const shutdown = new AbortController();
process.on('SIGTERM', () => shutdown.abort());
async function main(): Promise<void> {
while (!shutdown.signal.aborted) {
await processNextJob(shutdown.signal); // bounded poll; back off when there is no work
}
process.exit(0);
}
void main();
# worker/worker.py
import signal
from threading import Event
shutdown = Event()
signal.signal(signal.SIGTERM, lambda signum, frame: shutdown.set())
while not shutdown.is_set():
process_next_job(shutdown) # bounded poll, finish the current job before returning
Daemon から Vercel Queues を利用する
daemon は、Vercel Queues のポーリングモードで長時間稼働するコンシューマーです。メッセージは送信先のリージョンからしか受信できないため、明示的にリージョンを指定して @vercel/queue の PollingQueueClient を使用してください:
// worker/worker.ts
import { PollingQueueClient } from '@vercel/queue';
const { receive } = new PollingQueueClient({ region: 'iad1' });
const shutdown = new AbortController();
process.on('SIGTERM', () => shutdown.abort());
while (!shutdown.signal.aborted) {
const result = await receive('orders', 'fulfillment', async (message) => {
await processOrder(message); // acknowledged when this resolves, retried if it throws
}, { limit: 10 });
if (!result.ok && result.reason === 'empty') {
await new Promise((r) => setTimeout(r, 1000));
}
}
プロデューサーが送信するリージョンと同じリージョンで daemon を実行してください。デフォルトではトピックはデプロイ ID ごとにパーティション分割されます。デプロイをまたいだコンシュームに依存する前に、ポーリングモードのバージョニングのセクションをお読みください。プロデューサー側とプッシュモードのコンシューマーについては、⤳ skill: queues を読み込んでください。
環境変数と OIDC
- 各インスタンスには、デプロイの環境変数が渡されます。
- 各インスタンスには、
VERCEL_OIDC_TOKEN_FILEにパスが記載されたファイルに書き込まれる OIDC トークンが渡され、定期的に更新されます。@vercel/oidc4.0.0 以降(Node.js)またはvercel-oidc0.10.0 以降(Python)で読み取ってください。VERCEL_OIDC_TOKENしか読み取らない古い SDK バージョンでは、トークンを見つけられません。
ローカル開発
vercel dev は daemon を実行しません。警告を出力して、プロジェクトの残りの部分を起動します。代わりに Docker で daemon を実行してください:
vercel env pull # writes .env.local
docker build -t worker worker/
docker run --env-file .env.local worker
ログと可観測性
daemon の出力は、ソースが daemon、名前が daemon の名前としてプロジェクトの Logs に表示されるため、特定の daemon に絞り込めます。プロジェクトダッシュボードの Daemons タブには、各 daemon のインスタンス、ステータス、ログが表示されます。
ビルド出力 API
vercel build またはカスタムビルダーを使用すると、.vercel/output/config.json に daemon が "daemons": { "worker": {} } として一覧表示されます(全 daemon の一覧です。一覧にない daemon は停止されます)。各 daemon には .vercel/output/daemons/<name>/.vc-config.json があり、runtime: "container"、Vercel Container Registry に登録済みの image、instances、および任意の command と resources が含まれます。vercel build はイメージをビルドしてプッシュし、これらのファイルを自動的に書き込みます。
制限
| 制限 | 値 |
|---|---|
| リージョンあたりのインスタンス数 | daemon あたり 100 |
| インスタンスあたりのメモリ | 1、2(デフォルト)、4、または 8 GiB |
| シャットダウン猶予期間 | デフォルトでは SIGTERM の後 10 秒 |
| CPU アーキテクチャ | Linux amd64 |
ベータ期間中は、チームごとのデフォルトクォータが適用されます。Hobby は 1~2 GiB のインスタンスと月間 vCPU 時間の上限があり(上限に達するとインスタンスは停止します)、Pro では同時 vCPU 数とメモリの上限まであらゆるサイズを利用でき、Enterprise はカスタムです。デプロイのサイズを決める前に、最新の数値をDaemons limitsで確認してください。
ベータ期間中は、プレビューのデプロイ、インバウンド HTTP または TCP トラフィック、オートスケーリング、永続的なローカルストレージ(Vercel Blob または Marketplace のデータベースを使用してください)、vercel dev での実行、サービスバインディングまたはリライトのターゲットとしての利用、Dockerfile/Containerfile を使わないビルド、およびルートディレクトリが apps/web のようなサブフォルダーであるプロジェクトはサポートされていません。
よくある落とし穴
- トラフィックを期待する:ポートをリッスンする daemon は何も受信しません。Functions または Services でリクエストを処理し、daemon には作業をプルさせてください。
- プレビューでテストする:ベータ期間中、プレビューのデプロイでは daemon は起動しません。本番環境にデプロイするか、イメージをローカルで実行してください。
- スケーリングの変更が無視される:ダッシュボードでのスケーリングのオーバーライドが、解除されるまで
instancesより優先されます。 - 安全でない重複稼働:ロールアウト中は旧バージョンと新バージョンが並行して実行されます。メッセージ形式とスキーマ移行は後方互換性を保ってください。
- SIGTERM を処理しない:プロセスは
SIGTERMの 10 秒後に強制終了されます。ジョブを冪等にし、完了後にのみ確認応答してください。 commandでシェル構文を使う:$VARと&&は展開されません。sh -cで囲んでください。- モノレポのルートディレクトリ:ルートディレクトリがサブフォルダーのプロジェクトでは、まだ daemon を追加できません。
- 古い OIDC SDK:トークンファイルを読み取るには、
@vercel/oidc≥ 4.0.0 またはvercel-oidc≥ 0.10.0 を使用してください。
参考資料
- 📖 ドキュメント:https://vercel.com/docs/daemons
- 📖 設定リファレンス:https://vercel.com/docs/daemons/config-reference
- 📖 デーモンの管理:https://vercel.com/docs/daemons/managing-daemons
- 📖 制限とクォータ:https://vercel.com/docs/daemons/limits
- 📖 Build Output API:https://vercel.com/docs/build-output-api/daemons
- 📖 Queues のポーリングモード:https://vercel.com/docs/queues/poll-mode
- 📖 Functions と containers と Daemons の比較:https://vercel.com/kb/guide/vercel-functions-containers-daemons