n8n queue mode: scaling with workers
Updated 2026-10-21 · 5 min read
Queue mode is how self-hosted n8n scales past one process. The main instance keeps serving the editor, timers and webhooks, but it no longer runs executions itself: it puts them on a Redis queue, and any number of worker processes pick them up. This page explains the architecture, the configuration that every component needs, a working Compose example, and the details that break real deployments (binary data, task runners, large webhook responses).
Start with a single instance (Docker setup). Move to queue mode when executions pile up, the editor slows down during heavy runs, or you need to run more work in parallel than one Node.js process handles.
How it works
From the queue mode docs:
- The main instance handles timers and webhook calls and creates an execution, without running it.
- It puts the execution ID on Redis.
- A free worker takes the job from Redis.
- The worker loads the workflow from the database and runs it.
- It writes the result to the database and tells Redis the job is done.
- Redis notifies the main instance.
| Component | Runs | Needs |
|---|---|---|
| Main | Editor, API, triggers, test webhooks | Postgres, Redis |
Worker (n8n worker) |
Production executions | Postgres, Redis, same encryption key |
Webhook processor (n8n webhook, optional) |
Receives production webhook requests | Postgres, Redis, EXECUTIONS_MODE=queue |
| Redis | The queue | |
| Postgres | Workflows, credentials, executions | SQLite isn't supported here |
Required configuration
On main, workers and webhook processors:
| Variable | Value |
|---|---|
EXECUTIONS_MODE |
queue |
QUEUE_BULL_REDIS_HOST |
Redis host (default localhost) |
QUEUE_BULL_REDIS_PORT |
6379 by default |
QUEUE_BULL_REDIS_PASSWORD |
If Redis has one |
N8N_ENCRYPTION_KEY |
Identical on every process, or workers can't decrypt credentials |
DB_TYPE=postgresdb and DB_POSTGRESDB_* |
Same database everywhere |
Optional but common:
| Variable | Default | Purpose |
|---|---|---|
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS |
false |
Run manual (editor) executions on workers too |
N8N_GRACEFUL_SHUTDOWN_TIMEOUT |
30 s |
Time workers get to finish jobs on shutdown |
QUEUE_HEALTH_CHECK_ACTIVE |
off | Enables /healthz and /healthz/readiness on workers |
N8N_WEBHOOK_URL |
– | Public webhook base URL (2.30.0+) |
N8N_DISABLE_PRODUCTION_MAIN_PROCESS |
– | Main stops handling production webhooks when you use webhook processors |
All processes must run the same n8n version.
Compose example
Building on the single-instance file from n8n Docker setup, add Redis and a worker, and set queue variables in a shared block:
x-n8n-env: &n8n-env
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: "6379"
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_RUNNERS_MODE: external
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
services:
redis:
image: redis:7
restart: always
n8n:
image: n8nio/n8n:${N8N_VERSION}
environment:
<<: *n8n-env
N8N_WEBHOOK_URL: https://n8n.example.com/
ports: ["127.0.0.1:5678:5678"]
depends_on: [postgres, redis]
main-runners: # main still runs manual executions
image: n8nio/runners:${N8N_VERSION}
environment:
N8N_RUNNERS_TASK_BROKER_URI: http://n8n:5679
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
depends_on: [n8n]
n8n-worker:
image: n8nio/n8n:${N8N_VERSION}
command: worker --concurrency=10
environment:
<<: *n8n-env
depends_on: [n8n]
worker-runners:
image: n8nio/runners:${N8N_VERSION}
environment:
N8N_RUNNERS_TASK_BROKER_URI: http://n8n-worker:5679
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
depends_on: [n8n-worker]
Postgres and its volume are as in the single-instance file. Scale workers with additional worker services (each with its own runners sidecar).
Task runners in queue mode
The task runner docs are explicit: each worker needs its own runners sidecar. If OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS is false (the default), the main instance still runs manual executions and needs its own sidecar too. A worker without runners fails every Code node, which is the most common first-day queue mode problem. Custom npm or Python packages must be in every runners image.
Worker concurrency
A worker runs 10 executions in parallel by default; change it with n8n worker --concurrency=N. n8n recommends 5 or higher: many workers with low concurrency each hold database connections and can exhaust the pool. Our rule of thumb, not n8n's: add workers once one worker at concurrency 10 to 20 is consistently busy.
Webhook processors
For high webhook volume, run separate n8n webhook processes behind a load balancer:
- Route
/webhook/*and/webhook-waiting/*to the webhook processors. - Route everything else, including
/webhook-test/*(editor test runs), to main. - Don't put main in the webhook pool; it degrades the editor. Optionally set
N8N_DISABLE_PRODUCTION_MAIN_PROCESS=true.
Pitfalls
| Problem | Cause | Fix |
|---|---|---|
| Binary data missing between steps | Filesystem binary storage isn't supported in queue mode | N8N_DEFAULT_BINARY_DATA_MODE=database, or S3 external storage (Business/Enterprise) |
| Credentials fail on workers | Different encryption key | Same N8N_ENCRYPTION_KEY everywhere |
| Code nodes fail on workers | No runners sidecar on the worker | One sidecar per worker |
| "The response is too large to be sent back from the worker" | Respond to Webhook body over N8N_WEBHOOK_RESPONSE_RELAY_SIZE_MAX (64 MiB) |
Raise it, or offload to storage (2.34.0+) |
| Webhooks slower than before | Request now hops main → Redis → worker | Expected overhead; add webhook processors for volume |
Multi-main (Enterprise)
Queue mode can run several main processes for high availability: one leader runs at-most-once work (timers, pollers, pruning), followers serve the UI and API. It needs N8N_MULTI_MAIN_SETUP_ENABLED=true on every main, Postgres, Redis, the same version everywhere, and a load balancer with sticky sessions. It's a self-hosted Enterprise feature and isn't available on n8n Cloud.
Do you need it after leaving Pipedream?
Pipedream ran and scaled the infrastructure for you, and you paid per credit. On self-hosted n8n, one instance is enough for most migrated projects of a few dozen workflows. Queue mode becomes relevant with many high-frequency webhooks, long-running Code nodes, or heavy schedules that overlap.
Before sizing, look at what you're moving: our converter report shows trigger types and code steps per workflow, and the code step checker shows what a single step needs. The report and 1 workflow are free. Full export: $3 per workflow, $19 minimum — coming soon. Then follow migrate Pipedream to n8n.
Not affiliated with Pipedream or n8n.
FAQ
- What is queue mode in n8n?
- A self-hosted setup where the main instance receives triggers and webhooks, puts execution IDs on a Redis queue, and separate worker processes run the executions. You scale by adding workers.
- Which environment variables enable n8n queue mode?
- EXECUTIONS_MODE=queue on the main instance and every worker, QUEUE_BULL_REDIS_HOST and QUEUE_BULL_REDIS_PORT (plus password if set), the same N8N_ENCRYPTION_KEY everywhere, and a shared Postgres database.
- Can I use SQLite with queue mode?
- No. n8n doesn't support running a distributed setup over SQLite; use Postgres.
- How many executions does an n8n worker run at once?
- 10 by default. Change it with n8n worker --concurrency=N. n8n recommends 5 or higher; many workers with low concurrency can exhaust the database connection pool.
- Is queue mode available on n8n Cloud?
- On self-hosted n8n you configure it yourself. n8n's pricing page lists queue mode as included on Cloud Enterprise. Multi-main is self-hosted Enterprise; the docs say it isn't available on n8n Cloud.
Related
Sources
- https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/enable-queue-mode
- https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/queue-mode
- https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners
- https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/use-external-storage