IAnswerable

Scale n8n with Queue Mode and Workers

01 Dec 2025

A single n8n instance runs everything in one process: the UI, the webhook listener, and every workflow execution. One long-running workflow — a data export, a loop over a few thousand records — blocks that process and everything else waits behind it, including new webhook triggers. Queue mode splits execution out into separate worker processes so a slow workflow stops holding the rest of your automation hostage.

What queue mode actually changes

Without queue mode, n8n executes workflows in the same process that serves the editor UI and receives webhooks. With it, you run a main process that only handles the UI, API, and webhook reception, plus one or more worker processes that pull jobs off a Redis-backed queue and execute them. Webhooks still arrive instantly even if every worker is busy — the job just queues instead of blocking anything.

This requires two things you may not already have: Redis, and Postgres. SQLite can’t be shared safely across separate worker processes, so if you haven’t already moved off SQLite, do that first — queue mode won’t work without it.

flowchart LR
    W["Webhook"] --> M["Main process (UI, API)"]
    M -->|"enqueues job"| R["Redis queue"]
    R --> W1["Worker 1"]
    R --> W2["Worker 2"]
    R --> W3["Worker 3"]
    W1 --> P["Postgres"]
    W2 --> P
    W3 --> P
  

1. Add Redis

services:
  redis:
    image: redis:7-alpine
    restart: unless-stopped

2. Configure the main process

services:
  n8n:
    environment:
      EXECUTIONS_MODE: queue
      QUEUE_BULL_REDIS_HOST: redis
      QUEUE_BULL_REDIS_PORT: 6379
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
    depends_on:
      - redis
      - postgres

EXECUTIONS_MODE: queue is the switch. Without it, everything else here is ignored and n8n runs in the default single-process mode regardless of what else you’ve set.

3. Add worker processes

Workers are the same n8n image, started with a different command:

services:
  n8n-worker:
    image: n8nio/n8n
    restart: unless-stopped
    command: worker
    environment:
      EXECUTIONS_MODE: queue
      QUEUE_BULL_REDIS_HOST: redis
      QUEUE_BULL_REDIS_PORT: 6379
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
    depends_on:
      - redis
      - postgres
    deploy:
      replicas: 3

replicas: 3 gives you three workers pulling from the same queue. Scale this number up when you have more concurrent long-running workflows than workers to run them — check for jobs sitting in waiting state before assuming you need more, since adding workers you don’t need just adds idle processes.

4. Webhooks need a separate concern: response timing

There’s a subtlety here that trips people up. A webhook-triggered workflow, once queued, doesn’t block the HTTP response back to whatever called the webhook — n8n responds based on your webhook node’s response mode setting, not on workflow completion. If you have a webhook configured to wait for the workflow to finish and return its output, that response now has to wait on a worker to pick up and complete the job, which adds queue latency on top of execution time. For latency-sensitive webhooks, set the webhook node to respond immediately and handle the result asynchronously (write to a database, call back, whatever fits) rather than blocking on workflow completion.

Watching queue health

Check what’s queued versus running via Redis directly:

docker compose exec redis redis-cli LLEN bull:jobs:wait

A number that keeps climbing means jobs are arriving faster than your workers can drain them — that’s your signal to add replicas, not a mysterious slowdown to debug in the workflow logic.

What doesn’t change

The n8n editor UI, credentials, and workflow definitions are unaffected — queue mode is purely about where execution happens, not how you build workflows. You don’t need to modify a single existing workflow to move to queue mode; it’s an infrastructure change, not an application one. The main process still owns the UI and webhook reception, so if it goes down, new triggers stop arriving even though existing queued jobs keep processing on workers — plan your main process’s uptime accordingly, since it’s still a single point of failure for anything new coming in.