
Founder of Goodspeed
There is a moment every growing n8n instance hits. Executions start queueing behind each other, the interface feels sluggish, and a burst of webhooks that used to sail through now backs up for minutes. This is not a bug and it is not your workflows being badly built. It is the default single-process architecture reaching its ceiling.
Queue mode is n8n's answer. It changes how the platform runs so that many executions can happen in parallel across separate worker processes, backed by a Redis queue. It is the same pattern used by every serious task-processing system, and it is how self-hosted n8n goes from handling a handful of jobs to handling thousands reliably.
This guide explains why the default mode caps out, how queue mode actually works, how to set it up with Docker, how to tune concurrency, and when you genuinely need it. By the end you will know whether it is time to make the switch and how to do it without breaking what already works.
Why the default single-process mode caps out
Out of the box, n8n runs in what is called regular or main mode. A single Node.js process does everything: it serves the editor, receives webhooks, schedules triggers, and executes every workflow. That simplicity is perfect for getting started, and for light workloads it is all you will ever need. The problem is that one process can only do so much at once.
Because executions run inside that single process, a heavy workflow can hog CPU and memory while everything else waits. Node.js concurrency helps, but there is a hard ceiling, and when you cross it new executions queue up behind the ones already running. A long job or a sudden spike of triggers stalls the whole instance. You cannot scale a single process indefinitely, which is exactly the wall queue mode is designed to remove.
What queue mode actually is
Queue mode splits n8n into distinct roles instead of one process doing everything. It is a distributed architecture, and once you see the shape of it the setup makes sense. The core idea is that receiving work and doing work become separate jobs handled by separate processes, coordinated through a shared queue.
This is the standard producer and consumer pattern. One part of the system produces jobs, another part consumes and executes them, and a queue in the middle holds the backlog so nothing is lost when demand outpaces capacity. n8n uses Redis for that queue. The result is that you can add processing power simply by adding more consumers, without touching the part of the system that receives the work in the first place.
The three moving parts: main, Redis, and workers
A queue mode setup has three components. The main instance serves the editor UI, handles the API, receives webhooks, and fires scheduled triggers. Critically, in queue mode it no longer executes workflows itself. Instead it places each execution as a job onto the queue and hands the actual work off to the workers.
Redis sits in the middle as the message queue. It holds the jobs waiting to be processed and coordinates which worker picks up which job, so nothing is executed twice and nothing is dropped. The workers are separate n8n processes running in worker mode. Each one connects to the same Redis and the same database, pulls jobs off the queue, executes the workflows, and writes the results back. Add more workers and you add more capacity.
Why Redis is the backbone
Redis is not an optional extra in queue mode, it is the piece that makes the whole thing work. It is an in-memory data store that is extremely fast at exactly the operations a job queue needs: pushing jobs on, popping them off, and tracking their status. When your main instance produces a job, it lands in Redis, and whichever worker is free grabs it next.
Because Redis holds the queue independently of any single process, your setup becomes resilient. If a worker restarts, the jobs it had not yet finished are still tracked and can be picked up rather than lost. If a burst of triggers arrives faster than the workers can process them, they wait safely in the queue instead of overwhelming the system. Redis is what turns a set of separate processes into one coordinated, reliable platform.
Setting it up: EXECUTIONS_MODE=queue and the pieces around it
The switch that turns on queue mode is the environment variable EXECUTIONS_MODE=queue. Setting it tells n8n to stop executing workflows in the main process and start pushing them to the queue instead. On its own that variable is not enough, though. You also need to point n8n at your Redis instance and make sure every process shares the same database and encryption key.
You configure the Redis connection through the QUEUE_BULL_REDIS_HOST and related variables so the main instance and workers all talk to the same queue. The database must be PostgreSQL, not the default SQLite, because multiple processes will be reading and writing at once. And every process must share the same N8N_ENCRYPTION_KEY, otherwise workers cannot decrypt the credentials they need to run your workflows. Get those three things aligned and the architecture holds together.
A Docker Compose setup that works
In practice, most teams run queue mode with Docker Compose, because it lets you define every component in one file and start them together. A typical stack has five services: the n8n main instance, one or more n8n workers, PostgreSQL for the database, Redis for the queue, and often a separate webhook processor for high-traffic webhooks.
The main and worker services use the same n8n image with the same environment variables, differing only in the command they run. The main service runs normally, while each worker runs the worker command so it registers as a consumer rather than a producer. Because they share the environment, adding a second or third worker is as simple as duplicating the worker service or scaling it up. Compose keeps the whole distributed system reproducible, which matters when you need to rebuild or move it.
Adding workers to grow throughput
The whole point of queue mode is horizontal scaling, and workers are the lever. One worker gives you a fixed amount of parallel processing. Add a second and you roughly double your capacity, add a third and you triple it, all without changing your workflows or your main instance. Because workers are stateless consumers pulling from the same queue, they coordinate automatically.
This means you can match capacity to demand. If your executions are backing up during business hours, add workers. If load is spiky, you can even scale workers up and down on a schedule. On a single powerful machine you might run several worker processes to use all the cores, and on a cluster you can spread workers across multiple machines. Either way, growing throughput becomes an operational decision rather than a re-architecture.
Tuning N8N_CONCURRENCY_PRODUCTION_LIMIT
Each worker does not run just one job at a time. The N8N_CONCURRENCY_PRODUCTION_LIMIT variable controls how many executions a single worker handles concurrently. Raise it and each worker does more in parallel, which is efficient for light workflows that spend most of their time waiting on external APIs. Set it too high, though, and heavy workflows will starve the worker of CPU and memory.
The right number depends on your workloads. If your executions are lightweight and IO-bound, a higher concurrency squeezes more out of each worker. If they are CPU-heavy or memory-hungry, keep concurrency lower and add more workers instead. The practical approach is to start with a modest limit, watch CPU and memory under real load, and adjust. Tuning concurrency alongside worker count is how you get the most performance from the hardware you are paying for.
Handling webhooks at scale
Webhooks deserve their own attention in a queue mode setup. By default the main instance receives them, and if you are taking a high volume of inbound webhooks, that reception work can compete with everything else the main process is doing. For heavy webhook traffic, n8n lets you run dedicated webhook processor instances that only receive and enqueue webhooks.
The pattern mirrors the rest of queue mode. The webhook processors accept the incoming request, place the execution on the queue, and return quickly, while the workers do the actual processing in the background. This keeps webhook response times fast and consistent even under load, which matters when the sending service expects a prompt acknowledgement. Separating reception from execution is the same principle that makes the whole architecture scale.
When you actually need queue mode
Queue mode is powerful, but it is not for everyone, and adding Redis and multiple workers to a light workload is complexity you do not need. If you run a handful of workflows on a schedule and nothing is backing up, the default mode is genuinely fine and simpler to operate. Do not reach for queue mode to feel enterprise-grade, reach for it because you have a real bottleneck.
The signs are clear when they appear. Executions queue behind each other during busy periods. A long-running workflow blocks quicker ones. Bursts of webhooks or triggers overwhelm a single process. Your CPU or memory is maxed out and the interface lags. When you see these, you have outgrown single-process mode, and queue mode is the right next step rather than a bigger single box that will hit the same ceiling again.
Migrating without breaking what works
Moving an existing instance to queue mode is very achievable, but it rewards a bit of care. The prerequisites come first: migrate to PostgreSQL if you are still on SQLite, stand up Redis, and confirm your encryption key is set explicitly so it can be shared. These are the foundations that queue mode depends on, and getting them right up front avoids the most common migration headaches.
Then bring up the new architecture alongside your existing setup rather than flipping a switch in place. Start the main instance in queue mode, add a single worker, and run real workflows through it to confirm executions flow through the queue correctly. Once you trust it, scale up the workers and tune concurrency. Migrating deliberately, one step at a time, means you gain the scale without gambling the automations your business already relies on.
Monitoring your queue mode instance
A distributed system needs eyes on it. The single most useful signal in queue mode is queue depth: how many jobs are waiting in Redis to be processed. If that number is consistently near zero, your workers are keeping up. If it climbs and stays high, you need more workers or higher concurrency. Watching it turns capacity planning into a simple, visible decision.
Enable n8n's metrics with the N8N_METRICS variable to expose execution counts and durations, and keep an eye on the CPU and memory of your workers and Redis. Alert when the queue backs up or a worker goes unhealthy, so you find out before your users do. A well-monitored queue mode instance is calm and predictable, which is the entire reason for building it this way in the first place.
Queue mode is how n8n scales
Queue mode is how self-hosted n8n grows up. It replaces a single overloaded process with a main instance, a Redis queue, and as many workers as your load demands, so executions run in parallel instead of stacking up. The setup is a matter of EXECUTIONS_MODE=queue, PostgreSQL, Redis, a shared encryption key, and a sensible concurrency limit, all wired together cleanly with Docker Compose.
Reach for it when you have a real bottleneck, migrate deliberately, and monitor the queue depth so you always know whether to add workers. Done properly, it gives you automation that scales with your business rather than against it. If you want a team that builds automation you own, see our n8n case studies, including HubSync, or book a free call with our n8n team.

Written By
Founder of Goodspeed






