// Engineering Log

n8n: Part 5 — Scaling: queue mode, workers and task runners

Published on 2026-09-22

// Fast route

This article belongs to the topic Python and automation.

When a single n8n process can no longer handle the number of executions, it is scaled: workflow executions are offloaded to separate worker processes, webhook reception to separate processes, and user code to isolated task runners. How to enable queue mode is described in the second part of the series; here — how scaling is organized and how to manage it.

First, about “light” and “heavy” workers

In the community people often talk about splitting workers into “light” (fast workflows: webhooks, notifications) and “heavy” (file processing, long AI requests). It is important to understand: there are no named queues in n8n. The documentation does not have a QUEUES variable, nor a per-workflow queue setting, nor a N8N_WORKER_CONCURRENCY variable. All workers of a single deployment pull tasks from a single Redis queue, and you cannot choose which worker will execute a particular workflow.

You can split load in other ways — they are described below.

What a scaled deployment consists of

  • Main instance (main) — UI, API, schedules; puts executions into the queue.
  • Redis — the job queue.
  • Workers — n8n worker processes that pick up executions from the queue and run them.
  • Webhook processors — n8n webhook processes that receive incoming webhooks.
  • PostgreSQL — shared database; a distributed setup with SQLite is not supported.

All processes must use the same N8N_ENCRYPTION_KEY, otherwise workers will not be able to decrypt credentials. Binary data in queue mode cannot be stored on the filesystem — the documentation recommends external S3 storage.

Workers and concurrency

A worker is started with the command n8n worker. The number of simultaneous executions on a single worker is set with the --concurrency flag, default 10:

bash
n8n worker --concurrency=5

Load is scaled by two levers: the number of workers (horizontal) and the --concurrency of each (vertical). If workflows are memory-heavy — lower concurrency per worker and more workers; if they mostly wait on external APIs — you can raise concurrency.

A global safeguard is the N8N_CONCURRENCY_PRODUCTION_LIMIT variable: the maximum number of production executions running at the same time. Default is -1 — no limit.

Manual executions from the editor run on the main instance by default. To have them executed by workers as well, set OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true — the documentation recommends this for production.

Webhook processors

If workflows are triggered by webhooks, request reception is offloaded to separate processes:

bash
n8n webhook

The load balancer routes /webhook/* paths to a pool of webhook processors, and on the main instance processing of production webhooks is disabled via N8N_DISABLE_PRODUCTION_MAIN_PROCESS=true. This way a spike of incoming requests does not interfere with the UI.

Task runners

Code from the Code node is executed in task runners — separate processes isolated from n8n. Each runner by default executes up to 5 tasks concurrently (N8N_RUNNERS_MAX_CONCURRENCY), and a task is terminated after 300 seconds (N8N_RUNNERS_TASK_TIMEOUT).

There are two modes:

  • internal — the runner is started as a child process of n8n under the same user. Deprecated since n8n 3.0: code that escapes the sandbox gains access to everything available to n8n, including stored credentials;
  • external — a separate n8nio/runners container runs alongside n8n (the image version must match the n8n version), and communication is protected by a shared secret N8N_RUNNERS_AUTH_TOKEN.

In queue mode each worker needs its own runners container. The N8N_RUNNERS_ENABLED variable has been deprecated since n8n 2.0 — task runners are always enabled.

How to actually separate “light” and “heavy”

Since there is a single queue, separation is done at the level of deployments and workflows:

  1. A separate n8n deployment for heavy tasks. Its own main instance, its own Redis and its own workers — for example, for document processing or AI workloads. Light workflows call heavy ones via webhook or HTTP requests.
  2. Webhook processors separate from workers. Request reception stays fast even when workers are busy.
  3. Adjust concurrency to the nature of the load. For a deployment with heavy workflows — low --concurrency and more memory per worker.
  4. Move heavy code out of n8n. Long-running file processing is often simpler to perform in an external service, leaving n8n as the orchestrator.

Minimal set of variables

bash
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
DB_TYPE=postgresdb
N8N_ENCRYPTION_KEY=same-encryption-key-on-all-processes
OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true
N8N_RUNNERS_MODE=external
N8N_RUNNERS_AUTH_TOKEN=shared-secret

Common mistakes

  • Different encryption keys on the main instance and workers — workflows fail when decrypting credentials.
  • SQLite in queue mode — not supported.
  • Binary data on the main instance disk — workers cannot see it.
  • One runners container for the entire deployment — in queue mode each worker needs its own runners container.
  • Looking for a “workflow queue” setting — it does not exist; separate load by using separate deployments.

// Similar task

If you are dealing with something similar

This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.

Article topic

Python and automation

Bots, integrations, internal services, process automation, and workflows.

Typical tasks behind this topic

  • Build a bot, integration, or internal tool
  • Remove manual routine with Python and APIs
  • Connect services and automate the full workflow

// Next step

If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.

Open services

// Reviews

Related reviews

// Contact

Need help?

Get in touch with me and I'll help solve the problem

I reply within one business day (03:00-13:00 GMT)

Или оставьте заявку здесь:

Confirm that you are not a bot.

Write and get a quick reply