---
title: How to choose between Functions, containers, and Daemons on Vercel
description: Choose Vercel Functions for HTTP requests, container images for custom runtimes, and Daemons for continuous background workers.
url: "https://vercel.com/kb/guide/vercel-functions-containers-daemons"
published: 2026-10-15
last_updated: 2026-10-15
authors: Anshuman Bhardwaj
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

Use [Vercel Functions](https://vercel.com/docs/functions) for HTTP requests, container images when those Functions need a custom runtime or system dependencies, and Daemons for continuous background workers. Container images change what a Function runs; Daemons change how a worker runs.

| Consideration         | Functions deployed from source        | Functions using container images                   | Daemons                                        |
| --------------------- | ------------------------------------- | -------------------------------------------------- | ---------------------------------------------- |
| Work starts when      | A request arrives                     | A request arrives                                  | The worker receives or pulls work              |
| You deploy            | Application source                    | A container image                                  | A container image                              |
| Primary fit           | APIs, webhooks, server-side rendering | HTTP apps needing a custom runtime or dependencies | Continuous background workers                  |
| Receives inbound HTTP | Yes                                   | Yes                                                | No                                             |
| Capacity              | Scales automatically                  | Scales automatically                               | Fixed instances per region                     |
| Work lifecycle        | Bounded invocation                    | Bounded invocation                                 | Continuous process                             |
| Main responsibility   | Application code                      | Application code and Docker image                  | Worker code, Docker image, and instance counts |

## Choose by what starts the work

Choose Vercel Functions when an incoming request starts the work. Vercel invokes your code to handle the request and scales capacity with traffic.

Deploy a container image when your request handler needs a custom runtime or system dependencies. The image runs as a Vercel Function on Fluid compute, with automatic scaling and the same function limits.

Choose a Daemon when your worker needs to stay running and pull work from a queue, workflow engine, or external service. Examples include Temporal workers and self-hosted continuous integration (CI) runners. Daemons connect to their work source and don't receive inbound traffic.

## Use Functions for incoming requests

API routes, webhook handlers, and server-rendered pages run in response to requests. Each function invocation must finish within its configured duration limit.

Vercel integrates with supported [frameworks](https://vercel.com/docs/frameworks) and [runtimes](https://vercel.com/docs/functions/runtimes), so you can deploy application code without maintaining a server or container image.

### What is Fluid compute?

[Fluid compute](https://vercel.com/docs/fluid-compute) allows multiple invocations to share an instance. When one invocation waits on a database query or an external API, the instance can handle other work. Vercel adjusts capacity as demand changes and applies optimizations that reduce cold starts.

Function duration limits vary by plan and runtime. Work that takes several minutes may fit within those limits. Use [Vercel Workflows](https://vercel.com/docs/workflows) when you need retries, saved progress across steps, or pauses for external events.

### Running background work with Functions

Functions can send analytics or update a cache after returning a response, so that the work doesn't delay the caller.

Use [`waitUntil()`](https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil) in supported handlers to continue work after sending a response. For Next.js 15.1 and later, use the framework's `after()` API.

Both APIs share the function's duration limit. If the function times out, unfinished `waitUntil()` tasks are canceled.

## Use container images for custom runtimes and dependencies

Use a container image for a Java API, a PHP application, or an HTTP service that depends on a system library such as FFmpeg.

Container images package your application, runtime, and dependencies. Vercel runs each image as a Function on Fluid compute, scaling with incoming requests.

You maintain the `Dockerfile`, base image, and dependencies. For a framework Vercel already supports, deploying source code with its framework preset avoids maintaining a container image.

Your server must accept HTTP traffic on the configured port. Vercel detects `Dockerfile.vercel` at the project root, and [Services](https://vercel.com/docs/services) lets you deploy container applications alongside other parts of the project.

Functions using [Container Runtime](https://vercel.com/docs/functions/runtimes/container) scale down when idle. Packaging a polling worker in a container image doesn't keep it running continuously.

## Use Daemons for continuous background workers

Daemons keep background workers running so they can receive and process tasks from an external system. Use them for existing Celery, Sidekiq, BullMQ, or Temporal workers, or for self-hosted CI runners.

For a production deployment, Vercel builds the Daemon's container image and starts the configured number of instances. It restarts instances that exit or crash.

Add this configuration to `vercel.json` to run two worker instances in `iad1`:

```json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "daemons": {
    "worker": {
      "root": "worker/",
      "entrypoint": "Dockerfile",
      "instances": {
        "iad1": 2
      }
    }
  }
}
```

The `worker/` directory contains your worker code and `Dockerfile`. Each instance runs the same image and must be able to consume work independently.

### Handle worker interruptions

Daemons can stop during deployments, scaling changes, or failures. Before replacing an instance, Vercel sends `SIGTERM` and gives it 10 seconds to shut down before terminating it.

Stop accepting new work when your worker receives `SIGTERM`. Configure your queue or task system to retry interrupted work, and make handlers safe to repeat without duplicating completed effects.

For queue consumers, acknowledge messages after successful processing. Check your framework's recovery settings because delayed acknowledgment alone may not cause interrupted tasks to be retried.

During deployment, old and new instances can briefly run together. Worker versions need to tolerate consuming from the same source during that overlap.

### Plan worker capacity

Daemons run a fixed number of instances in each configured region and don't autoscale. Monitor whether workers keep up with incoming work and adjust instance counts via a new production deployment.

Daemons don't receive inbound HTTP or TCP traffic and have no persistent local storage. Store state in a database or external storage service.

Only production deployments start Daemons. Preview deployments don't run them. For local development, run the worker with Docker rather than `vercel dev`.

## Choose for common workloads

### Receiving a Stripe webhook

Handle a Stripe webhook with a Vercel Function. If fulfillment needs independent processing and retries, publish the follow-up work to [Vercel Queues](https://vercel.com/docs/queues). Use a push consumer to process the message without a polling worker.

### Bringing an existing .NET API to Vercel

Your team already has a .NET HTTP application with a tested `Dockerfile` and a specific set of system dependencies.

Deploy the application as a container image to run it as a Vercel Function on Fluid compute. Vercel scales it with requests while you maintain the runtime and image. Follow [Deploy ASP.NET Core on Vercel with Docker](https://vercel.com/kb/guide/dot-net-asp-net-on-vercel-with-docker) for the configuration.

### Running an existing BullMQ or Temporal worker

Your application already uses BullMQ for Redis jobs or Temporal to coordinate work. The worker connects to that system and stays running to receive tasks.

Run the existing worker as a Daemon. Vercel maintains the configured instance count, while your worker framework manages jobs and your code handles interrupted work and graceful shutdown.

For new jobs delivered to a Function, consider [Vercel Queues](https://vercel.com/docs/queues). Use [Vercel Workflows](https://vercel.com/docs/workflows) for durable sequences of steps.

### Generating reports during a traffic spike

Customers request PDF reports at month end. Waiting for each report slows responses, and request bursts can overwhelm downstream services.

Use Vercel Queues to buffer report requests for a consumer Function. Failed jobs can be retried, but each attempt must fit the consumer's execution limits.

At-least-once delivery requires consumers to handle duplicates safely.

Use Vercel Workflows when you need retries and saved progress across steps that collect data, generate and store reports, and notify customers.

### Waiting for approval in an onboarding flow

Your system checks a new customer's application and waits for a reviewer to approve it before provisioning their account. The process may take days even though each action takes only seconds.

Use Vercel Workflows to wait for an external approval event without losing progress. The workflow can resume later, even after crashes or deployments.

### Refreshing a product catalog every night

Your storefront imports updated prices and inventory from a supplier once a day. Between imports, there's no work for that process to do.

Use [Cron Jobs](https://vercel.com/docs/cron-jobs) to trigger a Function on that schedule. If the import needs several recoverable steps, the handler can start a workflow. Choose a Daemon when the integration needs continuous polling.

### Combining an API, background jobs, and existing workers

One ecommerce application can handle payment webhooks with Vercel Functions, generate receipts through Vercel Queues, and coordinate fulfillment through Vercel Workflows. Its Java inventory API can run as a Function using a container image, while an existing Temporal worker runs as a Daemon.

## Next steps

- [Running Docker on Vercel](https://vercel.com/kb/guide/docker): Develop, test, and deploy with Docker.
  
- [How Vercel Services run on Fluid compute](https://vercel.com/kb/guide/vercel-services-fluid-compute): Understand concurrency, scaling, and compute pricing.
  
- [Vercel Queues quickstart](https://vercel.com/docs/queues/quickstart): Publish and consume your first message.
  
- [Build an agent with human approvals](https://vercel.com/kb/guide/building-human-in-the-loop-agents-for-community-moderation-with-durable-workflows): Pause a moderation workflow for human review and resume it afterward.
  

## Frequently asked questions

### Can I run background jobs on Vercel?

Yes. Use [`waitUntil()`](https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil), or `after()` in Next.js 15.1 and later, for work after a response. Use Vercel Queues for independent jobs, [Cron Jobs](https://vercel.com/docs/cron-jobs) for scheduled work, and [Vercel Workflows](https://vercel.com/docs/workflows) for durable sequences of steps. Daemons run continuous background workers.

### What is the difference between a container and a Daemon on Vercel?

A container image packages your code, runtime, and dependencies. A Daemon runs a continuous background worker from a container image. Images can also run as request-driven [Vercel Functions](https://vercel.com/docs/functions/runtimes/container). Choose based on whether your application handles incoming requests or pulls work independently.

### When should I use waitUntil() instead of a Daemon?

Use [`waitUntil()`](https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil) for request-related work, such as sending analytics or updating a cache, that can finish within the function's duration limit. Tasks are canceled if the function times out. In Next.js 15.1 and later, use `after()`. Use a Daemon for a process that stays running and pulls new work independently.

### Can I run Celery, BullMQ, or Temporal workers on Vercel?

Yes. Package your worker using a supported `Dockerfile` or `Containerfile`, then declare it under the top-level `daemons` key in `vercel.json`. The worker connects to its queue or workflow engine to receive work.

### What happens to Daemons during deployment or rollback?

Vercel starts new Daemon instances before stopping the previous ones, so old and new worker versions can briefly overlap. Your workers must tolerate both versions consuming from the same work source.

A rollback restores the Daemon images and instance counts declared by the earlier deployment.

### Can Functions, containers, and Daemons share a project?

Yes. Declare Daemons under the top-level `daemons` key in `vercel.json`, alongside your framework application or [Services](https://vercel.com/docs/services).

## More Fluid compute guides

- [How to ship a FastAPI app on Vercel](/kb/guide/ship-a-fastapi-app-on-vercel): Deploy a FastAPI app to Vercel with zero configuration. Learn how the Python runtime, Vercel Functions, streaming, middleware, and cron jobs work together.
- [Build with a Flask starter template](/kb/guide/build-with-a-flask-starter-template): Deploy a Flask app to Vercel from a starter template. Compare the Flask Hello World starter, AI SDK, alt text generator, and Next.js templates, then ship to a live URL.
- [Build with a FastAPI starter template](/kb/guide/build-with-a-fastapi-starter-template): Browse FastAPI starter templates for Vercel and deploy one in a few steps. Compare minimal, AI, agent, and full-stack FastAPI templates on the Python runtime.