daemons
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel Daemons
Vercel Daemons
You are an expert in Vercel Daemons, the long-running background processes that run from a container image in the same project as an app.
Daemons are in Public Beta on all plans. Say so when you recommend them.
你是 Vercel Daemons 专家。Vercel Daemons 是与应用在同一项目中、从容器镜像运行的长时间后台进程。
Daemons 已在所有套餐上进入 Public Beta。推荐它们时请说明这一点。
What It Is
什么是它
A daemon is a named resource in a project that runs a fixed number of identical instances of one container image in each region you list. Vercel builds the image from the daemon's or , rolls it out when the deployment becomes the production deployment, restarts instances that exit or crash, and forwards / to the project's Logs. Daemons run on Fluid compute.
DockerfileContainerfilestdoutstderrDaemons cannot receive inbound traffic. They pull work from a queue, a workflow engine, or an external API.
daemon 是一种项目内的命名资源,它会在你列出的每个 region 中运行同一个容器镜像的固定数量的相同实例。Vercel 使用 daemon 的 或 构建镜像;当部署成为生产部署时,Vercel 会滚动发布该镜像;退出的实例或崩溃的实例会被重启;/ 则会转发到项目的 Logs。Daemons 运行在 Fluid Compute 上。
DockerfileContainerfilestdoutstderrDaemons 无法接收入站流量。它们从 queue、workflow engine 或 external API 拉取工作。
When to Use Daemons
何时使用 Daemons
Use a daemon when the process owns a continuous loop that retrieves work.
| Need | Use | Why |
|---|---|---|
| Always-on queue consumer (Vercel Queues poll mode, SQS, Kafka, Redis), Celery/Sidekiq/BullMQ worker, workflow-engine worker, self-hosted CI runner | Daemons | Long-running loop, fixed instances per region, no request needed |
| HTTP APIs, webhooks, streaming, WebSockets | Vercel Functions ( | Daemons can't receive traffic |
| Fire-and-forget background job, fan-out, buffering with Vercel invoking your handler | Vercel Queues push mode ( | Serverless, scales automatically, works in previews |
| Durable multi-step logic with sleep, hooks, or approvals | Vercel Workflows ( | Durable steps and replay |
| Run code on a schedule | Cron Jobs ( | Time-based trigger |
| Run untrusted or AI-generated code in isolation | Vercel Sandbox ( | Ephemeral microVMs |
| Multiple frontends and backends in one project | Vercel Services ( | Daemons sit next to services; they are not services |
If the user's work is request-driven, prefer Functions or Queues push mode. Reach for a daemon only when something must stay running.
当进程拥有一个用于获取工作的持续循环时,使用 daemon。
| 需求 | 使用 | 原因 |
|---|---|---|
| 始终运行的 queue 消费者(Vercel Queues poll mode、SQS、Kafka、Redis)、Celery/Sidekiq/BullMQ worker、workflow-engine worker、自托管 CI runner | Daemons | 长时间运行的循环、每个 region 固定数量的实例、无需发起请求 |
| HTTP API、Webhook、流式传输、WebSockets | Vercel Functions( | Daemons 无法接收流量 |
| Fire-and-forget 后台任务、fan-out、由 Vercel 调用 handler 进行缓冲 | Vercel Queues push mode( | Serverless、自动扩缩容、可在 preview 中运行 |
| 包含 sleep、hook 或审批的 Durable 多步骤逻辑 | Vercel Workflows( | Durable 步骤与重放 |
| 按计划运行代码 | Cron Jobs( | 基于时间的触发器 |
| 在隔离环境中运行不受信任或 AI 生成的代码 | Vercel Sandbox( | 临时 microVM |
| 在一个项目中包含多个前端和后端 | Vercel Services( | Daemons 与 Services 并列运行;它们不是 Services |
如果用户的工作由请求驱动,请优先使用 Functions 或 Queues push mode。只有当某项任务必须持续运行时,才使用 daemon。
Quick Start
快速开始
Add a in the worker's source directory:
Dockerfiledocker
undefined在工作进程的源代码目录中添加 :
Dockerfiledocker
undefinedworker/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"]
Declare the daemon under the top-level `daemons` key:
```json filename="vercel.json"
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"daemons": {
"worker": {
"root": "worker/",
"entrypoint": "Dockerfile",
"instances": { "iad1": 2 }
}
}
}The same configuration works in as a table. Deploy to production. Vercel builds the image, pushes it to Vercel Container Registry as , and starts two instances in .
vercel.toml[daemons.worker]daemon.workeriad1Daemons are always declared at the top level, never inside . They run alongside an existing app (Next.js, Services, or anything else) without changing how Vercel builds it.
servicesFROM node:24-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "worker.js"]
在顶层 `daemons` 键下声明 daemon:
```json filename="vercel.json"
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"daemons": {
"worker": {
"root": "worker/",
"entrypoint": "Dockerfile",
"instances": { "iad1": 2 }
}
}
}同一配置也可在 中写作 表。部署到生产环境后,Vercel 会构建镜像,将其以 的名称推送到 Vercel Container Registry,并在 启动两个实例。
vercel.toml[daemons.worker]daemon.workeriad1Daemons 始终在顶层声明,绝不能放在 内。它们可以与现有应用(Next.js、Services 或其他任何内容)并行运行,而无需改变 Vercel 构建该应用的方式。
servicesConfiguration Reference
配置参考
| Field | Type | Required | Notes |
|---|---|---|---|
| | Yes | Source directory, relative to |
| | Yes | Path to the |
| | Yes | Instances per region ID, each |
| | No | Replaces the image's |
| | No | |
- vs
instances: the publishedreplicasschema and the Build Output API usevercel.json.instancesis a deprecated alias that is ignored whenreplicasis set. If the project already usesinstances, leave it working, but writereplicasin new configuration.instances - Names: lowercase letters only, joined by ,
_, or one or more__(-,worker,email_sender; notcelery-beat,Worker,worker1), 64 characters max. Two names that collapse to the same image repository once repeated hyphens are merged, such as_workeranda-b, fail the build. A daemon and a service may share a name.a--b - Rejected fields: service fields such as ,
framework,runtime, andbuildCommandfail validation on a daemon.bindings - Build: images are built for Linux . Deployment environment variables are passed to the image build as build arguments.
amd64 - Shell features: is exec-form. Use
commandfor variable expansion.["sh", "-c", "exec node worker.js --id $WORKER_ID"] - No : the build fails if the image has neither
CMDnorENTRYPOINTandCMDis not set.command
json
{
"$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" } }
}
}
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| | 是 | 相对于 |
| | 是 | 相对于 |
| | 是 | 每个 region ID 的实例数,每项为 |
| | 否 | 替换镜像的 |
| | 否 | |
- 与
instances:已发布的replicasschema 和 Build Output API 使用vercel.json。instances是已弃用的别名,当设置了replicas时会被忽略。如果项目已经使用instances,可以保持其继续工作,但新配置应使用replicas。instances - 名称:只能使用小写字母,并以 、
_或一个或多个__连接(-、worker、email_sender;不能使用celery-beat、Worker、worker1),最长 64 个字符。如果两个名称在合并重复连字符后归并为同一个镜像仓库,例如_worker和a-b,则构建失败。daemon 与 service 可以使用相同名称。a--b - 不允许的字段:daemon 中使用 、
framework、runtime和buildCommand等 service 字段会触发验证失败。bindings - 构建:镜像面向 Linux 构建。部署环境变量会作为 build arguments 传入镜像构建过程。
amd64 - Shell 功能:采用 exec 形式。需要展开变量时,请使用
command。["sh", "-c", "exec node worker.js --id $WORKER_ID"] - 没有 :如果镜像既没有
CMD也没有ENTRYPOINT,并且未设置CMD,则构建失败。command
json
{
"$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" } }
}
}
}Lifecycle and Scaling
生命周期与扩缩容
- Production only during the beta. Daemons run only for the production deployment. Preview deployments do not start daemons; test changes by running the image locally.
- Rollout: when a deployment becomes production (deploy, promote, Instant Rollback, or a completed rolling release), Vercel starts the new instances and sends to the previous deployment's instances. For a short time both versions run at once, so both must be able to consume the same queue and tolerate the same database schema.
SIGTERM - Image, command, and environment variables belong to the deployment. Change them with a new production deployment.
- Scaling with : change
vercel.jsonand deploy to production. The map replaces the previous one; regions removed from it stop.instances - Scaling overrides: in the project dashboard, Daemons → select the daemon → Set Scaling Overrides. Overrides persist across deployments and win over until cleared with Clear scaling overrides. If a
instanceschange tovercel.jsonseems ignored, check for an override first. There is no autoscaling, and scaling from the CLI or API is not available yet.instances - Stop without deleting: set every region to or
0toinstances, or set a{}override from the dashboard.0 - Delete: remove the daemon from and deploy to production.
daemons - Paused projects stop all daemon instances; they start again when the project resumes.
- Beta 期间仅在生产环境运行。 Daemons 仅为生产部署运行。Preview 部署不会启动 daemons;请通过在本地运行镜像来测试更改。
- 滚动发布:当部署成为生产部署时(deploy、promote、Instant Rollback 或完成滚动发布),Vercel 会启动新实例,并向旧部署的实例发送 。短时间内两个版本会同时运行,因此二者都必须能够消费同一个 queue,并兼容同一个 database schema。
SIGTERM - 镜像、命令和环境变量属于部署的一部分。通过新的生产部署进行更改。
- 使用 扩缩容:修改
vercel.json并部署到生产环境。该 map 会替换之前的 map;从中移除的 region 将停止运行。instances - 扩缩容覆盖:在项目控制台中,进入 Daemons → 选择 daemon → 设置扩缩容覆盖(Set Scaling Overrides)。覆盖配置会跨部署持久保留,并优先于 ,直到通过**清除扩缩容覆盖(Clear scaling overrides)**将其清除。如果
instances中对vercel.json的更改似乎未生效,请先检查是否存在覆盖配置。当前不支持自动扩缩容,也无法通过 CLI 或 API 扩缩容。instances - 停止但不删除:将每个 region 的实例数设置为 ,或将
0设置为instances,也可以在控制台中设置{}覆盖值。0 - 删除:从 中移除 daemon,并部署到生产环境。
daemons - 已暂停的项目会停止所有 daemon 实例;项目恢复后,这些实例会重新启动。
Graceful Shutdown
优雅停机
Vercel sends on rollout, scale-down, removal, and manual restart, then waits 10 seconds by default before terminating the process. Stop taking new work immediately and finish the job in progress. Instances can stop at any time, so jobs must be idempotent and safe to retry; acknowledge a queue message only after processing it.
SIGTERMts
// 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();python
undefined在滚动发布、缩容、移除和手动重启时,Vercel 会发送 ,随后默认等待 10 秒再终止进程。应立即停止领取新工作,并完成正在处理的任务。实例可能随时停止,因此任务必须具备幂等性,并且能够安全重试;只有在处理完成后才能确认 queue message。
SIGTERMts
// 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();python
undefinedworker/worker.py
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
undefinedimport 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
undefinedConsuming Vercel Queues From a Daemon
从 Daemon 消费 Vercel Queues
A daemon is the long-running consumer for Vercel Queues poll mode. Use from with an explicit region, because messages can only be received from the region they were sent to:
PollingQueueClient@vercel/queuets
// 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));
}
}Run the daemon in the same region the producer sends to. Topics are partitioned by deployment ID by default; read the poll-mode versioning section before relying on cross-deployment consumption. For the producer side and push-mode consumers, load .
⤳ skill: queuesdaemon 是 Vercel Queues poll mode 的长时间运行消费者。请使用 中的 并显式指定 region,因为消息只能从其被发送到的 region 中接收:
@vercel/queuePollingQueueClientts
// 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 部署在与生产者发送到同一 region。Topics 默认按 deployment ID 分区;在依赖跨 deployment 消费之前,请先阅读 poll-mode 的版本控制章节。如需了解生产者端和 push-mode 消费者,请加载 。
⤳ skill: queuesEnvironment Variables and OIDC
环境变量与 OIDC
- Each instance receives the deployment's environment variables.
- Each instance receives an OIDC token written to a file whose path is in , refreshed periodically. Read it with
VERCEL_OIDC_TOKEN_FILE4.0.0 or later (Node.js) or@vercel/oidc0.10.0 or later (Python). Older SDK versions that only readvercel-oidcwill not find it.VERCEL_OIDC_TOKEN
- 每个实例都会收到该 deployment 的环境变量。
- 每个实例都会收到一个写入文件的 OIDC token,文件路径由 指定,并且会定期刷新。请使用
VERCEL_OIDC_TOKEN_FILE4.0.0 或更高版本(Node.js),或@vercel/oidc0.10.0 或更高版本(Python)读取该文件。只读取vercel-oidc的旧版 SDK 将找不到该文件。VERCEL_OIDC_TOKEN
Local Development
本地开发
vercel devbash
vercel env pull # writes .env.local
docker build -t worker worker/
docker run --env-file .env.local workervercel devbash
vercel env pull # writes .env.local
docker build -t worker worker/
docker run --env-file .env.local workerLogs and Observability
日志与可观测性
Daemon output appears in the project's Logs with source and the daemon's name, so you can filter to one daemon. The project dashboard's Daemons tab shows each daemon's instances, status, and logs.
daemondaemon 输出会出现在项目 Logs 中,source 为 ,并带有 daemon 的名称,因此可以筛选到特定 daemon。项目控制台的 Daemons 选项卡会显示每个 daemon 的实例、状态和日志。
daemonBuild Output API
Build Output API
With or a custom builder, lists daemons as (the complete set; omitted daemons are stopped), and each has with , an already in Vercel Container Registry, , and optional and . builds and pushes the images and writes these files for you.
vercel build.vercel/output/config.json"daemons": { "worker": {} }.vercel/output/daemons/<name>/.vc-config.jsonruntime: "container"imageinstancescommandresourcesvercel build使用 或自定义 builder 时, 会将 daemons 列为 (这是完整集合;未列出的 daemons 会停止运行),每个 daemon 都有对应的 ,其中包含 、已位于 Vercel Container Registry 的 、,以及可选的 和 。 会为你构建并推送镜像,并写入这些文件。
vercel build.vercel/output/config.json"daemons": { "worker": {} }.vercel/output/daemons/<name>/.vc-config.jsonruntime: "container"imageinstancescommandresourcesvercel buildLimits
限制
| Limit | Value |
|---|---|
| Instances per region | 100 per daemon |
| Memory per instance | 1, 2 (default), 4, or 8 GiB |
| Shutdown grace period | 10 seconds after |
| CPU architecture | Linux |
Default per-team quotas apply during the beta: Hobby is limited to 1–2 GiB instances and a monthly vCPU-hour allowance (instances stop when it runs out), Pro allows all sizes up to a concurrent vCPU and memory cap, and Enterprise is custom. Check Daemons limits for the current numbers before sizing a deployment.
Not supported during the beta: preview deployments, inbound HTTP or TCP traffic, autoscaling, persistent local storage (use Vercel Blob or a Marketplace database), running in , being the target of a service binding or rewrite, builds without a /, and projects whose root directory is a subfolder such as .
vercel devDockerfileContainerfileapps/web| 限制 | 值 |
|---|---|
| 每个 region 的实例数 | 每个 daemon 100 个 |
| 每个实例的内存 | 1、2(默认)、4 或 8 GiB |
| 停机宽限期 | 收到 |
| CPU 架构 | Linux |
Beta 期间会应用默认的团队级配额:Hobby 仅可使用 1–2 GiB 实例,并受每月 vCPU-hour 配额限制(配额用尽后实例会停止);Pro 允许使用所有规格,但受并发 vCPU 和内存上限约束;Enterprise 可定制。在确定部署规格之前,请查看 Daemons limits 以了解当前数值。
Beta 期间尚不支持:preview 部署、入站 HTTP 或 TCP 流量、自动扩缩容、持久化本地存储(请使用 Vercel Blob 或 Marketplace database)、在 中运行、作为 service binding 或 rewrite 的目标、缺少 / 的构建,以及根目录为 等子文件夹的项目。
vercel devDockerfileContainerfileapps/webCommon Pitfalls
常见问题
- Expecting traffic: a daemon that listens on a port receives nothing. Serve requests with Functions or Services, and have the daemon pull work.
- Testing on a preview: daemons never start for preview deployments during the beta. Deploy to production or run the image locally.
- Ignored scaling change: a dashboard scaling override wins over until it is cleared.
instances - Unsafe overlap: old and new versions run side by side during a rollout. Keep message formats and schema migrations backward compatible.
- No SIGTERM handling: the process is killed 10 seconds after . Make jobs idempotent and acknowledge only after completion.
SIGTERM - Shell syntax in :
commandand$VARare not expanded. Wrap in&&.sh -c - Monorepo root directory: projects with a subfolder root directory cannot add daemons yet.
- Stale OIDC SDK: use ≥ 4.0.0 or
@vercel/oidc≥ 0.10.0 so the token file is read.vercel-oidc
- 期望接收流量:监听端口的 daemon 不会收到任何内容。请使用 Functions 或 Services 提供请求服务,并让 daemon 拉取工作。
- 在 preview 上测试:Beta 期间 daemons 永远不会为 preview 部署启动。请部署到生产环境或在本地运行镜像。
- 扩缩容更改被忽略:控制台中的扩缩容覆盖配置优先于 ,直到将其清除。
instances - 不安全的重叠运行:滚动发布期间,旧版本和新版本会并行运行。请保持消息格式和 schema migration 向后兼容。
- 未处理 SIGTERM:进程会在收到 10 秒后被终止。请让任务具备幂等性,并且仅在完成后确认消息。
SIGTERM - 在 中使用 shell 语法:
command和$VAR不会被展开。请使用&&包裹。sh -c - Monorepo 根目录:根目录为子文件夹的项目目前无法添加 daemons。
- OIDC SDK 过旧:请使用 ≥ 4.0.0 或
@vercel/oidc≥ 0.10.0,以便读取 token 文件。vercel-oidc
References
参考资料
- 📖 docs: https://vercel.com/docs/daemons
- 📖 configuration reference: https://vercel.com/docs/daemons/config-reference
- 📖 managing daemons: https://vercel.com/docs/daemons/managing-daemons
- 📖 limits and quotas: https://vercel.com/docs/daemons/limits
- 📖 Build Output API: https://vercel.com/docs/build-output-api/daemons
- 📖 Queues poll mode: https://vercel.com/docs/queues/poll-mode
- 📖 Functions vs containers vs Daemons: https://vercel.com/kb/guide/vercel-functions-containers-daemons
- 📖 文档:https://vercel.com/docs/daemons
- 📖 配置参考:https://vercel.com/docs/daemons/config-reference
- 📖 管理 Daemons: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 poll mode:https://vercel.com/docs/queues/poll-mode
- 📖 Functions、Containers 与 Daemons 的区别:https://vercel.com/kb/guide/vercel-functions-containers-daemons