Mindket
n8n advanced courseLesson 4 of 4

n8n queue mode: Redis, workers, concurrency and scaling

A black banner titled "n8n advanced" over the line "Errors, sub-workflows, code and scaling".

n8n queue mode splits the work between a main instance, Redis and worker processes. The main instance receives triggers and webhooks and queues each execution in Redis, and a worker picks it up and runs it. It needs PostgreSQL, Redis, one shared encryption key and a binary data mode other than filesystem. A worker runs 10 jobs at a time by default.

In this lesson

  • Know when queue mode is worth its extra moving parts.
  • Run main, Redis, Postgres and workers on one shared encryption key.
  • Tune worker concurrency and the Redis settings that matter.
  • Pick a binary data mode that works with several workers.
  • Route webhooks to processors and know what multi-main needs.
All courses
On this page
  1. Before you start
  2. How a queued execution runs
  3. Set up a main, a worker and Redis
  4. Concurrency, Redis and timeouts
  5. Binary data and large webhook responses
  6. Webhook processors and the load balancer
  7. Multi-main for high availability
  8. What n8n's team and the n8n Helm chart say about running at scale
  9. Common mistakes
  10. Try it yourself
  11. Next course: Dify
  12. Check yourself
  13. Frequently asked questions
  14. Sources

Before you start

Queue mode is a self-hosted setup. The basics of running n8n in Docker are in the self-hosting lesson, and this lesson starts where that one stops. The queue mode page describes four pieces. A main instance takes the triggers and webhook calls. Worker instances run the executions. Redis is the message broker, and the database persists the data.

PostgreSQL is the database to use. The docs call queue mode on SQLite not recommended and a distributed setup over SQLite unsupported. The database page lists PostgreSQL 17 and 18 as supported as of July 2026, plus 16 for compatibility.

Queue mode adds Redis, a shared database and one process per worker, so try the lighter option first. In regular mode n8n puts no limit on concurrent production executions, and the concurrency page says too many can thrash the event loop. Setting N8N_CONCURRENCY_PRODUCTION_LIMIT queues the excess inside one process. Move to queue mode once one process is the limit, not before.

How a queued execution runs

A worker is the same n8n program started in a different role. The docs say each worker is its own Node.js instance that can handle several executions at once. All production executions run on workers. A webhook request still lands on the main instance or a webhook processor, which hands the execution over, and the docs warn that this can add overhead and latency.

Manual executions join them from n8n 3.0, in early access since 27 October 2026. The breaking-changes page says they always run on workers in queue mode and removes OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS, so check how much memory your workers have. The path of one execution has six steps:

One execution, from trigger to result
  1. Main takes the trigger

    The main instance handles timers and webhook calls and generates a workflow execution without running it.

  2. The ID goes to Redis

    It passes the execution ID to Redis, which keeps the queue of pending executions.

  3. A worker picks it up

    The next available worker in the pool takes the message from Redis.

  4. The worker loads the workflow

    It uses the execution ID to read the workflow information from the database.

  5. The worker saves the result

    After the run it writes the results to the database and posts to Redis that the execution has finished.

  6. Main is told

    Redis notifies the main instance.

Set up a main, a worker and Redis

The n8n-hosting repository has a reference stack with Postgres, Redis, a main instance, one worker and a task runner sidecar for each. The excerpt below is trimmed from it, with the omitted parts marked. The file also sets OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true, which the breaking-changes page lists as removed, so we left that line out.

Every process needs the same N8N_ENCRYPTION_KEY, because the queue mode page says workers need the main instance's key to read credentials stored in the database. Each worker also needs its own task runner sidecar, which is why the file pairs n8n-worker with n8n-worker-runner, as the task runner page requires. Outside Compose you start a worker with n8n worker, and the docs' Docker form is docker run --name n8n-queue -p 5679:5678 n8nio/n8n worker.

x-shared: &shared
  restart: always
  image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
  environment:
    - DB_TYPE=postgresdb
    - DB_POSTGRESDB_HOST=postgres
    - EXECUTIONS_MODE=queue
    - QUEUE_BULL_REDIS_HOST=redis
    - QUEUE_HEALTH_CHECK_ACTIVE=true
    - N8N_ENCRYPTION_KEY=${ENCRYPTION_KEY}
    - N8N_RUNNERS_MODE=external
    - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN}
    - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
  # ... database settings, volume and depends_on omitted

services:
  # ... x-runner, postgres, redis, n8n and n8n-runner omitted
  n8n-worker:
    <<: *shared
    command: worker
    depends_on:
      - n8n

  n8n-worker-runner:
    <<: *runner
    environment:
      - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN}
      - N8N_RUNNERS_TASK_BROKER_URI=http://n8n-worker:5679
    depends_on:
      - n8n-worker
  1. Copy the docker-compose/withPostgresAndWorker folder from the n8n-hosting repository.
  2. Change the default users, passwords and tokens in its .env file before you start, as the README warns. The compose file also reads N8N_VERSION, ENCRYPTION_KEY and RUNNERS_AUTH_TOKEN, so set those too.
  3. Run docker compose up -d.
  4. Check the worker from another container on the same Docker network. With QUEUE_HEALTH_CHECK_ACTIVE=true, its /healthz/readiness endpoint on port 5678 says whether the database and Redis connections are ready.
  5. Publish a workflow with a Webhook trigger and call its production URL. The execution should run on the worker, not on main.

Concurrency, Redis and timeouts

A worker runs ten jobs in parallel unless you pass the concurrency flag, as in n8n worker --concurrency=5. n8n recommends 5 or higher. The queue mode page warns that low values with a large number of workers can exhaust the database connection pool, which leads to processing delays and failures.

One variable sits above the flag. N8N_CONCURRENCY_PRODUCTION_LIMIT is -1 by default, and in queue mode n8n takes the limit from it when it holds any other value. Otherwise it falls back to the flag or its default, says the concurrency page.

Measure before you add workers. The docs report up to 220 executions per second on one 4 GB instance, but that run used only a Webhook and an Edit Fields node, so your workflows will differ. For a managed Redis, QUEUE_BULL_REDIS_TLS turns on TLS, and QUEUE_BULL_REDIS_CLUSTER_NODES switches n8n to a Redis Cluster client that ignores the host and port.

Figures from n8n's scaling pages

220

executions per second the docs report for one 4 GB instance running a Webhook and an Edit Fields node

Source: n8n Docs: Measure performance (read November 4, 2026)

10

jobs a worker runs in parallel by default

Source: n8n Docs: Enable queue mode (read November 4, 2026)

5

the lowest worker concurrency n8n recommends

Source: n8n Docs: Enable queue mode (read November 4, 2026)

64 MiB

the largest webhook response a worker relays through Redis by default

Source: n8n Docs: Queue mode environment variables (read November 4, 2026)

From the queue mode variables page and the queue mode page.
VariableDefaultWhat it does
QUEUE_BULL_REDIS_HOSTlocalhostThe Redis host
QUEUE_BULL_REDIS_PORT6379The Redis port
QUEUE_BULL_REDIS_DB0The Redis database
QUEUE_BULL_REDIS_TIMEOUT_THRESHOLD10000How long, in ms, n8n waits while Redis is unavailable before it exits
QUEUE_WORKER_LOCK_DURATION60000The lease, in ms, that a worker holds on a message
QUEUE_WORKER_LOCK_RENEW_TIME10000How often, in ms, a worker renews that lease
QUEUE_WORKER_STALLED_INTERVAL30000How often, in ms, a worker checks for stalled jobs, with 0 for never
N8N_GRACEFUL_SHUTDOWN_TIMEOUT30Seconds a worker gets to finish its jobs before the process ends
QUEUE_HEALTH_CHECK_ACTIVEfalseTurns on the worker's health check endpoints

Binary data and large webhook responses

The queue mode page says n8n does not support queue mode with binary data stored on the filesystem. The docs then point two ways. The handle binary data page says to switch to database. The queue mode page points to S3 external storage for workflows that persist binary data. Both appear in the table.

The new major version changes the defaults under you. It removes the in-memory default mode, and the breaking-changes page says an instance that still uses it switches to filesystem on upgrade. The binary data variables page still lists default as the default, so set N8N_DEFAULT_BINARY_DATA_MODE yourself.

A webhook response travels from the worker back to main inside a Redis message. The N8N_WEBHOOK_RESPONSE_RELAY_SIZE_MAX variable caps it at 64 MiB, and the docs advise budgeting about 1.5 times that in Redis memory for each response in flight. From n8n 2.34.0, setting N8N_WEBHOOK_RESPONSE_RELAY_OFFLOAD_ENABLED=true on the workers stores a larger body in binary data storage instead of failing the node. Upgrade every main and webhook instance first, because an older one hands the client the storage reference instead of the body.

From the queue mode page, the handle binary data page, the external storage page and the binary data variables page.
ModeWith queue modeNotes
filesystemNot supportedThe queue mode page says n8n does not support it
databaseNamed by the handle binary data pageN8N_BINARY_DATA_DATABASE_MAX_FILE_SIZE defaults to 512 MiB and cannot exceed 1024, the limit of a database column
s3Named by the queue mode pageSelf-hosted Business or Enterprise with an active license key, and a bucket lifecycle rule because n8n leaves pruning to S3
azureRecommended for large responsesThe same license rule as S3, and a lifecycle policy on the container for pruning
defaultRemoved in n8n 3.0Kept binary data in memory

Webhook processors and the load balancer

Webhook processors are an optional layer that scales incoming requests. You start one with n8n webhook and set EXECUTIONS_MODE=queue on it too. It listens on the same port as main, 5678 by default, behind a load balancer. The docs advise against putting the main instance in that pool, because heavy load there degrades the editor.

Set N8N_WEBHOOK_URL on the main instance to your public webhook URL. It is available from n8n 2.30.0. The older WEBHOOK_URL still works as an alias, but the endpoints page marks it deprecated from 2.35.0, with a warning in the log at startup. To stop main from handling production webhooks at all, set N8N_DISABLE_PRODUCTION_MAIN_PROCESS=true and keep main out of the webhook pool.

From the queue mode page, for one domain shared by the editor and the webhooks.
PathRoute it toWhat it carries
/webhook/*The webhook processor poolWebhook trigger node endpoints
/webhook-waiting/*The webhook processor poolHuman-in-the-loop endpoints of send-and-wait nodes, such as the Slack node
/webhook-test/*The main instanceThe default URL for manual executions
Everything elseThe main instanceThe internal API and the editor files

Multi-main for high availability

A single main instance does two jobs. It handles regular tasks such as the API, the UI and webhooks, and at-most-once tasks such as timers, pollers and pruning. Multi-main runs several main instances for high availability. The docs split the roles into followers for regular tasks and one leader for both kinds, and a follower takes over if the leader becomes unavailable.

  • It is a self-hosted Enterprise feature and is not available on n8n Cloud.
  • Every main runs in queue mode, connects to Postgres and Redis and sets N8N_MULTI_MAIN_SETUP_ENABLED=true.
  • All main and worker processes run the same n8n version.
  • The mains sit behind a load balancer with sticky sessions.
  • The leader key lives 10 seconds and the leader check runs every 3 by default, set with N8N_MULTI_MAIN_SETUP_KEY_TTL and N8N_MULTI_MAIN_SETUP_CHECK_INTERVAL.

What n8n's team and the n8n Helm chart say about running at scale

On 9 June 2026 the n8n team announced on X that n8n now supports OpenTelemetry natively. Its argument is that workflows now run payments, support, CRM syncs and AI agents, so a failure deserves the visibility of any other service. With workers spread across machines, traces give you one place to follow each execution.

n8n's OpenTelemetry page says n8n can export workflow and node execution traces over OTLP to an OpenTelemetry collector. N8N_OTEL_ENABLED is off by default and exists from n8n 2.19.0, and N8N_OTEL_TRACES_INCLUDE_NODE_SPANS decides whether node spans are included.

For Kubernetes, the n8n Helm chart that 8gears maintains on GitHub maps these pieces onto a cluster. Its README says the chart spawns two worker instances, set with scaling.worker.replicaCount, and spawns no Redis server by default. Turning on scaling.webhook.enabled stops the main instance from processing webhooks.

When something breaks, you deserve the same visibility you'd have for any other service.

n8n.io, n8n's official account · X (read November 5, 2026)
n8n.io (@n8n_io) on X, 9 June 2026. n8n now supports OpenTelemetry natively. Your workflows aren't side projects anymore, they're production systems running payments, support, CRM syncs, and AI agents. When something breaks, you deserve the same visibility you'd have for any other service.
n8n.io on X, 9 June 2026

A screenshot of X's own embed of the post, taken on 5 November 2026, with the time in UTC. X cuts the post short with Show more. Select it to open the post on X.

Common mistakes

  • A worker with its own encryption key. The docs say the key of the main instance must reach every worker and webhook processor, or they cannot read the stored credentials.
  • Leaving EXECUTIONS_MODE=queue off a webhook processor. The docs say webhook processes rely on Redis and need the variable set too.
  • Still setting OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS or QUEUE_WORKER_MAX_STALLED_COUNT. The breaking-changes page removes the first, and the second has had no effect since n8n 2.0. The variables page still lists both.
  • Sharing one task runner sidecar between workers, or running a runners image of another version. Each worker needs its own sidecar, and the n8nio/runners image must match the n8nio/n8n image.
  • Raising the Postgres image from 16 to 18 on an existing volume. The README says it stops with "FATAL: database files are incompatible with server", and it warns you to keep the PGDATA line in the file.
  • Using Simple Memory for a chat agent in production on a queue-mode instance. The Simple Memory page says it does not work there, so pick Redis Chat Memory or Postgres Chat Memory, as the AI agent lesson shows.
  • Pointing several workers at one event log file. When workers share a writable filesystem, give each process its own N8N_EVENTBUS_LOGWRITER_LOGFULLPATH, an absolute path that ends in .log, as the log streaming page explains.

Try it yourself

  • Bring up the reference stack with your own secrets, call a webhook workflow at its production URL and open the execution in the editor.
  • Add --concurrency=5 to the worker command and compare how many executions run at once.
  • Stop the worker container, trigger the webhook once and note what the execution does until you start the worker again.
  • Read the worker's /healthz/readiness from inside the Docker network, stop Redis and read it again.

Next course: Dify

This is the last lesson of the n8n advanced course. The next course, the Dify tutorial, builds AI apps and workflows in Dify, a platform made for LLM apps with a knowledge base and agents built in. To put your new n8n setup to work, pick a ready-made workflow from the n8n workflow directory and import it as the import guide shows.

Check yourself

  1. What does n8n need for queue mode besides the main instance and the workers?

    Show answer

    D. Redis as the broker and a Postgres database Redis holds the queue and the database persists the data, so access to both is required, and a distributed setup over SQLite is not supported.

  2. A worker cannot open credentials that the main instance saved. What do you check first?

    Show answer

    A. That it uses the same N8N_ENCRYPTION_KEY The main instance key must be shared with every worker and webhook processor so they can read the stored credentials.

  3. Which binary data mode does n8n not support in queue mode?

    Show answer

    C. filesystem The queue mode page says n8n does not support queue mode with binary data stored on the filesystem.

  4. You put webhook processors behind a load balancer. Which path stays on the main instance?

    Show answer

    B. /webhook-test/* The webhook and webhook-waiting paths go to the processor pool, while the test URL for manual executions stays on main.

Frequently asked questions

Does n8n queue mode need Redis and Postgres?

Yes. Redis keeps the queue of pending executions, and PostgreSQL holds the workflows, credentials and results that every process shares. The docs say a distributed setup over SQLite is not supported.

How many workers do I need?

The docs give no formula. n8n recommends a worker concurrency of 5 or higher, and its own multi-instance benchmark used four workers and two webhook instances. Size yours from your own peak load.

Is multi-main available without an Enterprise license?

No, a license is needed, and the docs list multi-main for self-hosted Enterprise only. n8n Cloud does not offer it, and queue mode with one main and several workers carries no such note.

Where does binary data go in queue mode?

Use database mode, or S3 or Azure Blob storage on a self-hosted Business or Enterprise license, because filesystem mode is out. The in-memory default mode was removed too.

Do workers need task runners for the Code node?

In external mode, yes, and the reference compose file shows the pairing: n8n-worker-runner serves n8n-worker, just as n8n-runner serves the main instance. Internal mode is deprecated.

Where do manual test runs execute in queue mode?

They always run on workers now, and the OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS setting is gone. The test webhook URL still routes to the main instance.

Sources

  1. n8n Docs: Enable queue mode (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/enable-queue-mode
  2. n8n Docs: Queue mode environment variables (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/queue-mode
  3. n8n Docs: Control concurrency (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/control-concurrency
  4. n8n Docs: Measure performance (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/measure-performance
  5. n8n Docs: Handle binary data (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/handle-binary-data
  6. n8n Docs: Binary data environment variables (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/binary-data
  7. n8n Docs: Use external storage (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/use-external-storage
  8. n8n Docs: Choose your n8n database (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/choose-n8ns-database
  9. n8n Docs: Set up task runners (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/set-up-task-runners
  10. n8n Docs: v3.0 breaking changes (read November 4, 2026)https://docs.n8n.io/changelog/v30-breaking-changes
  11. n8n-hosting repository: Postgres and worker compose file (read November 4, 2026)https://github.com/n8n-io/n8n-hosting/blob/main/docker-compose/withPostgresAndWorker/docker-compose.yml
  12. n8n-hosting repository: Postgres and worker README (read November 4, 2026)https://github.com/n8n-io/n8n-hosting/blob/main/docker-compose/withPostgresAndWorker/README.md
  13. n8n Docs: Simple Memory node (read November 4, 2026)https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memorybufferwindow
  14. n8n Docs: Stream logs to external systems (read November 4, 2026)https://docs.n8n.io/administer/observe-and-log/stream-logs-to-external-systems
  15. n8n Docs: Executions environment variables (read November 4, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/executions
  16. n8n Docs: Endpoints environment variables (read November 5, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/endpoints
  17. n8n Docs: OpenTelemetry environment variables (read November 5, 2026)https://docs.n8n.io/deploy/host-n8n/configure-n8n/basic-configuration/use-environment-variables/opentelemetry
  18. n8n.io on X: n8n now supports OpenTelemetry natively, 9 June 2026 (read November 5, 2026)https://x.com/n8n_io/status/2064271339179897307
  19. 8gears on GitHub: n8n Helm chart (read November 5, 2026)https://github.com/8gears/n8n-helm-chart

Share this lesson

Import a workflow into your queue setup

Pick a ready-made n8n workflow on Mindket, check its nodes in a live preview and import it into the instance you just built.

Browse n8n workflows

This lesson as Markdown · n8n advanced course · All courses