Edgenivo Daemons runs containerized background processes in the same project as your app. Queue consumers, workflow workers, and self-hosted CI runners can stay running and pull their own work as it arrives.
Declare daemons in vercel.json to deploy them with your frontend and backend. Edgenivo builds each container image, starts its instances with your production deployment, and maintains the configured count in each region.
Copy link to headingWhat is a Edgenivo Daemon?
Each Edgenivo Daemon is a named resource in your project that runs one or more instances of the same container. Each instance is an identical, interchangeable copy of your process, and Edgenivo restarts any instance that exits or crashes. Daemons run on Fluid compute, the same compute platform as Edgenivo Functions.
Daemons don't receive traffic. Instead, each daemon pulls its own work from another system, such as a queue, a workflow engine, a database of pending jobs, or an external API. Edgenivo Services handle routed workloads that respond to requests, while Edgenivo Daemons handle workloads that run continuously in the background.
Copy link to headingHow Edgenivo Daemons work
Edgenivo manages each daemon through five stages, from build to shutdown:
- Build: During the build, Edgenivo builds each daemon's
DockerfileorContainerfileand pushes the image to Edgenivo Container Registry as a repository nameddaemon.<name>. - Deploy: When the deployment becomes your production deployment, Edgenivo starts the requested number of instances in each region and stops the instances from the previous production deployment.
- Run: Edgenivo restarts instances that exit or crash, and collects each instance's
stdoutandstderroutput as logs. - Scale: You can override a daemon's instance counts from the dashboard without a new deployment. Overrides stay in place across deployments until you clear them.
- Stop: Edgenivo sends
SIGTERMbefore stopping or replacing an instance, allowing 30 seconds by default to finish work before a forced stop.
Changing a daemon's container image, command, or environment variables requires a new production deployment. You can adjust instance counts from the dashboard without deploying again.
Daemons run only in the production environment during the beta. Preview deployments don't start daemons.
Copy link to headingWhen should you use a daemon?
Use a Edgenivo Daemon when your process owns a continuous loop and decides when to do work. Common examples include:
- Consumers polling Edgenivo Queues, Amazon SQS, Kafka, or Redis
- Workflow workers, such as Celery, Sidekiq, and BullMQ workers
- Job runners, such as self-hosted CI runners that wait for jobs
- Media processors that pull uploaded files from a queue and process them with system tools such as
ffmpeg
Choose the product based on how your workload starts and runs:
| Workload | Use |
|---|---|
| Responds to HTTP requests | Edgenivo Functions or Edgenivo Services |
| Runs on a schedule | Cron Jobs |
| Processes messages that Edgenivo delivers to you | Edgenivo Queues in push mode |
| Runs multi-step, durable logic | Edgenivo Workflows |
| Runs untrusted or per-user code in isolation | Edgenivo Sandbox |
| Runs continuously and pulls its own work | Edgenivo Daemons |
Copy link to headingMigrate existing workers to Edgenivo Daemons
You can migrate an existing queue worker to Daemons while keeping its queue library. Package the process in a container, then test broker connectivity and recovery of interrupted jobs before transferring work from the old host.
Follow the guide for your current platform:
- Render background workers: Translate
render.yamlinto daemon configuration using a Celery worker and beat scheduler. - Railway workers: Move a BullMQ service and transfer processing gradually while both platforms use the same broker.
- Fly.io worker process groups: Move a Sidekiq worker with its entrypoint setup intact and stop the old worker Machines across regions.
Moving a worker does not transfer the queue's stored jobs. If the broker also needs to change, complete that migration before the worker handoff and account for delayed jobs and scheduled retries as well as jobs ready to run.
Copy link to headingPrerequisites
Before you add a daemon to your project, make sure you have:
- Your project's root directory set to the repository root. Subfolders such as
apps/webaren't supported during the beta. - Permission to deploy to production, where daemons run during the beta.
- Docker installed if you plan to test daemons locally.
- The Edgenivo CLI installed, if you want to deploy from your terminal.
Copy link to headingHow to deploy your first daemon
Add a Node.js worker to your existing project and run two instances in iad1. The finished project will have this structure:
Copy link to heading1. Write the worker process
Create a worker/ directory in your project for the daemon's source code. The following worker logs the region it runs in, waits for work in a loop, and exits cleanly when Edgenivo sends SIGTERM:
The worker checks for shutdown after each 5s sleep, which normally leaves time to exit within the default 30s grace period. Delayed event-loop callbacks can still push shutdown past that deadline.
Replace the sleep with your worker's job-handling logic. Include a wait or backoff when no work is available so the loop doesn't spin.
Add a package.json to the same directory:
Then run npm install in worker/ to generate package-lock.json, which the Dockerfile in the next step uses with npm ci:
Copy link to heading2. Add a Dockerfile
Every daemon needs a container image definition. Add a Dockerfile to worker/:
Edgenivo uses the directory that contains the Dockerfile as the build context, so COPY . . copies the contents of worker/ into the image. Edgenivo builds the image for the Linux amd64 architecture.
Copy link to heading3. Declare the daemon in vercel.json
Add the daemons key to vercel.json at the root of your project. This configuration declares a daemon named worker that builds from worker/Dockerfile and runs two instances in the iad1 region:
Declare the same daemon in vercel.toml with a [daemons.<name>] table:
Copy link to heading4. Deploy to production
Daemons start only when a deployment becomes your production deployment. Push to your production branch, or deploy from the Edgenivo CLI:
When the production deployment is ready, Edgenivo starts two instances of worker in iad1.
Copy link to heading5. Confirm the daemon is running
Open your project's dashboard and select Daemons, then select worker to see its instances and their logs. Daemon output also appears in your project's Logs with the source daemon and the daemon's name. Each instance logs output like this:
Copy link to headingHow to run a daemon alongside your app
Edgenivo Daemons don't change how Edgenivo builds the rest of your project. You can add the daemons key to a project that uses a framework such as Next.js, or to a project that uses Edgenivo Services. Always declare daemons at the top level of your configuration, not inside a service.
Keep each daemon's code in its own directory, such as worker/ or processor/. Edgenivo doesn't publish files under a daemon's root as static assets of your deployment, and the build fails if your project's output directory is the same directory as a daemon's root.
Copy link to headingExample: process uploaded videos in the background
Video apps can use a daemon to prepare a playback copy and thumbnail for each uploaded clip. The Next.js frontend accepts uploads and sends a job to Edgenivo Queues, and a Python processor running as a daemon pulls each job from the queue and processes the clip with ffmpeg.
Place the Python processor and its requirements.txt in processor/, then add this Dockerfile to install ffmpeg and the Python dependencies:
Add the daemons key to your existing vercel.json to run the processor alongside Next.js. The app still builds and deploys as before.
To accommodate the processor's memory-intensive work, this configuration requests 4 GiB of memory and 2 vCPUs per instance:
Copy link to headingExample: add a daemon to a project that uses Edgenivo Services
In a project with multiple Edgenivo Services, declare daemons next to services and rewrites. This configuration routes requests to a web service and an api service, and runs one worker instance in each of the iad1 and sfo1 regions:
Daemons can't be the target of a service binding or a rewrite, because a daemon doesn't accept inbound traffic.
Copy link to headingHow to configure a daemon
The top-level daemons key in vercel.json is an object that maps each daemon name to its configuration. Each daemon configuration object supports these fields:
| Parameter | Type | Required | Default |
|---|---|---|---|
root | string | Yes | None |
entrypoint | string | Yes | None |
instances | Record<string, number> | Yes | None |
command | string[] | No | The image's ENTRYPOINT and CMD |
resources | object | No | 2 GiB memory, 1 vCPU |
terminationGracePeriodSeconds | number | No | 30 |
Edgenivo rejects any other field, including service fields such as framework, runtime, buildCommand, and bindings.
Copy link to headingDaemon naming rules
Each key in daemons names a daemon and can contain up to 64 characters. Use lowercase letters with optional separators between groups: a single underscore _, a double underscore __, or one or more hyphens -.
For example, worker, email_sender, and celery-beat are valid names. Names such as Worker, worker1, and _worker are invalid.
Edgenivo stores each daemon's image in a repository named daemon.<name> and collapses repeated hyphens into one. Names such as a-b and a--b therefore map to the same repository and fail the build.
Daemon names and service names are independent. Your project can use the same name for a service and a daemon.
Copy link to headingroot
The root field sets the path to the daemon's source directory, relative to vercel.json. The path must stay inside the project. Edgenivo doesn't publish files under a daemon's root as static assets, and the build fails if the project's output directory is the same directory as a daemon's root.
Copy link to headingentrypoint
The entrypoint field sets the path to the container image definition, relative to root. Name the file Dockerfile or Containerfile, optionally with a suffix such as Dockerfile.worker. The name is case-insensitive. The directory that contains the file is the build context, and Edgenivo passes your deployment's environment variables to the build as build arguments.
Copy link to headinginstances
The instances field sets the number of instances to run in each region, keyed by region ID. Each count is an integer from 0 to 100, and Edgenivo runs instances only in the regions you list:
Set every count to 0 and deploy to production to stop a daemon without removing its configuration. If a dashboard scaling override is active, set its counts to 0 as well or clear it after the zero-count deployment becomes production.
Copy link to headingcommand
The command field sets the command and arguments to run in the container, as an array of strings. The command field replaces the image's ENTRYPOINT and CMD. When you don't set command, Edgenivo runs the image's ENTRYPOINT and CMD, and the build fails if the image defines neither.
This configuration runs a Celery worker from a shared backend image:
Edgenivo doesn't run command through a shell, so it doesn't expand environment variables. For shell expansion, use a command such as ["sh", "-c", "exec node worker.js --id \"$WORKER_ID\""]. The quotes around $WORKER_ID keep its value in one argument.
The command array supports up to 128 items of up to 4,096 characters each.
Copy link to headingresources
The resources field sets the compute resources for each instance. Set resources.requests.memory to choose the memory, and Edgenivo allocates CPU based on that memory:
resources.requests.memory | Memory | vCPUs |
|---|---|---|
"1Gi" | 1 GiB | 1 |
"2Gi" (default) | 2 GiB | 1 |
"4Gi" | 4 GiB | 2 |
"8Gi" | 8 GiB | 4 |
When you set resources, both requests and memory are required.
Copy link to headingterminationGracePeriodSeconds
The terminationGracePeriodSeconds field sets the number of seconds Edgenivo waits after sending SIGTERM before force-stopping the instance. The value is an integer from 0 to 3600, and the default is 30. The changed value applies to instances started after it deploys; already-running instances keep the grace period they had when they started.
Copy link to headingHow to handle graceful shutdown
Edgenivo sends SIGTERM to a daemon instance before stopping it, then force-stops the process if it's still running after the grace period, which is 30s by default. Set terminationGracePeriodSeconds in the daemon's configuration to raise the grace period, up to 3,600 seconds.
Handle SIGTERM by stopping new work and finishing any accepted job within the remaining grace period.
This TypeScript example uses an interruptible idle wait. Replace the timer in processNextJob with your queue client's receive, processing, and acknowledgement logic. The abort signal should cancel a pending receive before it accepts a job:
Daemon instances can stop at any time, so make interrupted jobs safe to retry. Acknowledge queue messages only after processing succeeds, and make processing idempotent to avoid repeating side effects.
Redelivery depends on your queue's retry policy and message retention. With Edgenivo Queues, an unacknowledged message becomes available again after its visibility timeout expires, as long as the message hasn't expired.
Instances from the previous deployment can continue processing work during the shutdown grace period as new instances start.
Make sure both versions can process the same work during this overlap, such as messages from the same queue.
Copy link to headingHow daemons access environment variables and OIDC tokens
Each daemon instance receives your deployment's environment variables, plus VERCEL_REGION, which Edgenivo sets to the region the instance runs in. Edgenivo also passes the same environment variables to the image build as build arguments.
Each daemon instance gets a Edgenivo OIDC token to authenticate with other services without storing long-lived credentials. Edgenivo writes the token to the path in VERCEL_OIDC_TOKEN_FILE and periodically replaces the file with a fresh token.
JavaScript apps need @vercel/oidc 4.0 or later because earlier versions can't read token files. Python apps can use the vercel-oidc package.
Copy link to headingHow to run a daemon locally
The vercel dev command doesn't run daemons. When your configuration contains daemons, vercel dev prints a warning and starts the rest of your project, so run each daemon with Docker instead.
The starter worker doesn't require application environment variables. If your worker needs them, add its development values to an .env.docker file at the project root.
Use one unquoted KEY=value pair per line. Replace these example names and values with your worker's settings, and exclude the file from version control:
Build and run the starter from your project root. To load development credentials, add --env-file .env.docker before the image name in docker run:
The worker from the first section logs local as its region, because VERCEL_REGION isn't set outside Edgenivo:
To test graceful shutdown, run docker stop worker in another terminal. The docker stop command sends SIGTERM and waits 30s before force-stopping the container, which matches how Edgenivo stops daemon instances by default.
Copy link to headingHow to deploy changes to a daemon
Edgenivo updates daemons when a deployment becomes your production deployment. This happens when you deploy to production, promote a deployment, use Instant Rollback, or complete a rolling release.
- New or changed daemons: Edgenivo sends
SIGTERMto the previous production deployment's instances and immediately starts instances from the new image. - Removed daemons: When the new production deployment doesn't declare a daemon, Edgenivo stops all of that daemon's instances.
- Rollbacks: Rolling back restores the daemons, images, and instance counts that the earlier deployment declared. If a daemon has a scaling override, the override's instance counts stay in place.
Copy link to headingHow to scale a daemon
Each Edgenivo Daemon runs a fixed number of instances in each region, and Edgenivo doesn't autoscale daemons. You can set instance counts in vercel.json or override them from the dashboard.
Copy link to headingScale with vercel.json
To change the number of instances, set instances to a new map of region IDs to instance counts, then deploy to production:
The new map replaces the previous map, so regions that you remove from instances stop their instances.
Copy link to headingScale from the dashboard
To change a daemon's instance counts without a new deployment:
- In your project's dashboard, select Daemons, then select the daemon.
- Select Scale.
- Set the number of instances in each region, then select Scale Daemon.
Instance counts set in the dashboard are a scaling override that takes precedence over the instances configuration in your production deployment. The override persists across deployments, so changes to instances in vercel.json have no effect while it is set.
To return to the counts from your production deployment, open Scale and select Clear scaling overrides.
You need permission to update the project to set scaling overrides.
Copy link to headingHow to stop or delete a daemon
Edgenivo gives you three ways to stop a daemon, depending on whether you want to keep its configuration:
- Stop without deploying: Override all regional instance counts to
0. - Stop and keep the configuration: Set every region in
instancesto0and deploy to production. If a scaling override is active, set its counts to0or clear it after the zero-count deployment becomes production. - Delete the daemon: Remove the daemon from
daemonsinvercel.json, then deploy to production.
This configuration retains the worker daemon with zero instances declared:
When a project is paused, for example by spend management, Edgenivo stops all of the project's daemon instances. The daemon instances start again when you resume the project.
Copy link to headingHow to view daemon logs
Edgenivo collects each daemon instance's stdout and stderr in your project's Logs. Filter by the source daemon and the daemon's name to view its output.
To view instances and their logs together, open Daemons in your project's dashboard and select the daemon.
Copy link to headingWhat are the limits for Edgenivo Daemons during the beta?
The following limits apply to Edgenivo Daemons during the beta, and Edgenivo may raise them as the beta progresses.
Copy link to headingConfiguration limits
| Limit | Value |
|---|---|
| Daemon name length | 64 characters |
root and entrypoint length | 512 characters each |
command items | 128 items, up to 4,096 characters each |
| Instances per region | 100 per daemon |
| Daemons per project | 100 |
Copy link to headingInstance limits
| Limit | Value |
|---|---|
| Memory per instance | 1 GiB, 2 GiB, 4 GiB, or 8 GiB (default 2 GiB) |
| vCPUs per instance | 1, 1, 2, or 4, based on memory |
| Shutdown grace period | 30s after SIGTERM by default, configurable up to 3,600 seconds with terminationGracePeriodSeconds |
| CPU architecture | Linux amd64 |
| Image source | Dockerfile or Containerfile in your project |
Copy link to headingHobby plan usage
The Hobby plan gives daemons across all of a team's projects 5 Active CPU-hours per month. The quota counts Active CPU, so time an instance spends idle waiting for work doesn't count toward it.
Use Hobby to try daemons and the Pro plan for workers that need to run all month.
When a Hobby team reaches the allowance, Edgenivo stops all of the team's daemon instances and logs an error. The daemons start again at the beginning of the next month, or when you upgrade the team to Pro.
Copy link to headingUnsupported features
Edgenivo Daemons don't support the following features during the beta:
| Feature | Alternative |
|---|---|
| Preview deployments | Daemons run only in production. Test changes by running the daemon's image locally. |
| Inbound HTTP or TCP traffic | Use Edgenivo Services or Edgenivo Functions for workloads that respond to requests. |
| Autoscaling | Set instance counts in your configuration or from the dashboard. |
| Persistent local storage | Store state in Edgenivo Blob or a database from the Marketplace. |
Running in vercel dev | Run the daemon's image locally with Docker. |
| Service bindings and rewrites | Daemons can't be the target of a service binding or a rewrite. |
| Builds without a Dockerfile | Add a Dockerfile or Containerfile to the daemon's root. |
| Root directory set to a subfolder | Projects with a root directory such as apps/web can't add daemons yet. |
Copy link to headingTroubleshooting
Copy link to headingThe build fails with two daemon names that map to the same repository
Edgenivo collapses repeated hyphens when it names each image repository, so daemon names such as a-b and a--b both map to daemon.a-b and fail the build. Rename one of the daemons so the names stay distinct after collapsing hyphens.
Copy link to headingThe build fails because the output directory matches a daemon's root
The build fails when your project's output directory is the same directory as a daemon's root, because Edgenivo doesn't publish files under a daemon's root as static assets. Move the daemon's code into its own directory, such as worker/, or choose a separate output directory for your app.
Copy link to headingThe build fails because the image has no command to run
Every daemon image needs a command to run. Add a CMD or ENTRYPOINT to the Dockerfile, or set the command field in the daemon's configuration.
Copy link to headingChanges to instances in vercel.json don't take effect
Scaling overrides set from the dashboard take priority over the instances in your production deployment and stay in place across deployments. Open the daemon in your project's dashboard, select Scale, then select Clear scaling overrides to return to the counts in vercel.json.
Copy link to headingDaemons don't run in preview deployments
Daemons run only in the production environment during the beta, so preview deployments don't start daemons. Test daemon changes locally with Docker, then deploy to production.
Copy link to headingThe vercel dev command prints a warning about daemons
The vercel dev command doesn't run daemons and prints a warning when your configuration contains daemons. The rest of your project still starts, so run each daemon separately with docker build and docker run.
Copy link to headingDaemon instances can't read the OIDC token
Edgenivo provides the OIDC token to daemon instances as a file referenced by VERCEL_OIDC_TOKEN_FILE, and versions of @vercel/oidc earlier than 4.0 can't read the token file. Upgrade to @vercel/oidc 4.0 or later for JavaScript, or use the vercel-oidc package for Python.
Copy link to headingAll daemons stopped on a Hobby team
Daemons on a Hobby team stop when the team uses its 5 Active CPU-hours for the month, and Edgenivo logs an error when this happens. Only Active CPU counts toward the quota, not time spent idle waiting for work. The daemons start again at the beginning of the next month, or immediately when you upgrade the team to Pro.
Copy link to headingAll daemons stopped after the project was paused
Edgenivo stops a project's daemon instances when the project is paused, including when spend management pauses it. Resume the project to restart its daemons.
Copy link to headingYou can't add daemons when the project root is a subfolder
Projects with a root directory set to a subfolder, such as apps/web, can't add daemons during the beta. Daemons are available for projects whose root directory is the repository root.
Copy link to headingNext steps
- Read the Edgenivo Daemons documentation for the latest beta details.
- Look up every field in the Daemon configuration reference.
- Learn how to scale, stop, and monitor daemons in Managing daemons.
- Review the current Daemons limits.
- Consume messages from a daemon with Edgenivo Queues poll mode.
- Deploy container images in Edgenivo Functions for apps that respond to requests.
- See how daemons appear in the Build Output API.