How n8n Nodes Execute: Run Order, Queue Mode & Memory Allocation


⚡ n8n Workflow Automation
T3 · Node Execution Engine

How n8n Nodes Execute: Run Order, Queue Mode & Memory Allocation

n8n’s execution engine is built on a stack‑based, sequential processing
model
implemented by the WorkflowExecute class — it maintains a node
execution stack, processes nodes one by one via
processRunExecutionData(), and routes data downstream through
addNodeToBeExecuted(). The WorkflowRunner serves
as the primary entry point, deciding at execution time between regular
mode
(direct in‑process execution via
runMainProcess()) and queue mode (distributed
execution via enqueueExecution() through a Redis‑backed Bull job
queue). Queue mode requires PostgreSQL because SQLite cannot handle concurrent
multi‑process writes, uses Redis ≥6.0 as the message broker, and distributes
jobs to worker processes that independently fetch workflow
definitions from PostgreSQL, execute nodes, and write results back [1]
[2].

2
Execution Modes (Regular / Queue) [1]

v0 / v1
Execution Order Versions [3]

6
Steps in Queue Mode Flow [2]

Node.js 18
Runtime Engine [4]

Dimension Regular Mode Queue Mode
Execution Model Single-process: API, UI, webhooks, and execution all in one Node.js process [5] Distributed: main process handles UI/API/triggers; workers handle execution via Redis [2]
Best For Small deployments, development, testing [6] Production, high-volume, horizontal scaling [6]
Redis Required ❌ No [5] ✅ Yes (Redis ≥6.0 + Bull) [5]
Database SQLite or PostgreSQL [6] PostgreSQL (required) [6]
Enabled Via Default [5] EXECUTIONS_MODE=queue [6]

How does n8n’s stack-based engine determine node execution order in parallel branches?

n8n processes nodes sequentially using a stack-based model
maintained by the WorkflowExecute class: it initialises a node
execution stack
with the trigger, processes each node via
processRunExecutionData(), captures its output JSON, and
routes data to downstream nodes with addNodeToBeExecuted(),
repeating until the stack empties. The engine supports two execution
orders: v0 (legacy) and v1 (recommended).
[1]
[3]

In v1 mode, n8n completes each branch in turn before
moving to the next — branches are ordered by their position on the
canvas from topmost to bottommost; if two branches sit at the same
height, the leftmost executes first. In v0 mode, n8n
executes the first node of every branch, then the second node of every
branch, and so on — interleaving execution across branches. The execution
order is configurable per workflow under Workflow Settings → Parallel
Branch Execution Order. V1 is recommended for all workflows created in
version 1.0 and above; v0 remains available as a legacy option for
compatibility. The ActiveExecutions service tracks all
currently running executions, managing response promises for webhook-
triggered workflows and providing cancellation via
finalizeExecution() [1].
For a complete walkthrough of the WorkflowExecute class and the
runMainProcess() vs enqueueExecution()
decision, see the n8n Node Execution Hub.

How does queue mode distribute workflow executions using Redis, workers, and PostgreSQL?

Queue mode splits n8n into three logical component types: the
main process serving the editor UI, REST API, and
trigger listening; Redis ≥6.0 acting as the message
broker via the Bull job queue library; and worker processes
continuously polling Redis for jobs, executing workflows independently
via WorkflowExecute, and writing results back to PostgreSQL [2]
[5].

Queue mode requires PostgreSQL because SQLite cannot
handle concurrent multi-process writes: multiple worker processes must
read and write workflow definitions, execution state, and results
simultaneously — SQLite’s file-level write lock causes “database is
locked” errors and corruption under this load [6].
PostgreSQL handles this natively through MVCC with row-level locking.
The complete six‑step flow: (1) trigger reception generates
an execution, (2) execution record stored in PostgreSQL, (3) execution ID
pushed to Redis Bull queue, (4) next available worker pops the job, (5)
worker fetches full workflow definition and credentials from PostgreSQL,
(6) worker executes all nodes and writes results back to PostgreSQL [2].
Workers are stateless: you can add or remove them without downtime, and a
single worker failure never loses queued jobs. The encryption
key
(N8N_ENCRYPTION_KEY) must be identical across
the main process and every worker. For the complete production deployment
blueprint with Docker Compose, see the n8n Docker Compose production stack guide.

How does N8N_CONCURRENCY_PRODUCTION_LIMIT control how many workflows run simultaneously?

N8N_CONCURRENCY_PRODUCTION_LIMIT is a single environment
variable that caps the number of production executions running at the
same time — in both regular and queue modes. It
defaults to -1 (disabled). When set to any value other
than -1, it overrides the per-worker --concurrency flag in
queue mode and becomes the global ceiling for the entire deployment. This
limit applies only to production executions from webhooks and trigger
nodes — manual executions, sub-workflow calls, error executions, and CLI
executions are exempt [7].

Set it to a reasonable value (e.g., export N8N_CONCURRENCY_PRODUCTION_LIMIT=20)
to prevent event-loop thrashing caused by too many simultaneous production
executions [7].
In queue mode, if this variable is -1, each worker’s concurrency is
determined by its --concurrency startup flag (default:
10 per worker) [8].
The per-worker default of 10 means each worker runs up to 10 jobs in
parallel; a value less than 5 can lead to an unstable environment [8].
Executions beyond the limit are queued and processed in FIFO
order
as slots free up. On instance startup, n8n resumes queued
executions up to the concurrency limit and re-enqueues the rest. The
environment variable’s value is consumed once at startup; runtime changes
require a restart [7].
For complete scaling strategies including worker-to-core ratios and
high-availability configurations, see the n8n Scaling & Queue Configuration guide.

⚡ Concurrency Quick Reference: (1) Set
N8N_CONCURRENCY_PRODUCTION_LIMIT=20 to prevent event-loop
thrash in regular mode. (2) In queue mode, this variable overrides
per-worker --concurrency (default 10 per worker). (3)
Concurrency less than 5 can cause instability. (4) Excess executions
are queued in FIFO order. (5) This limit applies only to production
executions — manual, sub-workflow, error, and CLI executions are exempt.
[7]

How does n8n manage memory, how much does each execution consume, and what causes OOM errors?

n8n does not restrict the amount of data each node can fetch and process
— it uses a Node.js 18 runtime where the V8 engine
manages heap memory. Memory consumption scales with three
primary factors
: the volume of JSON data passing through nodes,
the size of binary data, and the number of nodes in a workflow.
Code nodes and the legacy Function node increase consumption
significantly [9].

On n8n Cloud, the memory limit varies by plan: 320–640 MiB
for Starter/Pro [10].
On self-hosted instances, you can increase the V8 heap size via
NODE_OPTIONS="--max-old-space-size=SIZE" or scale the
container memory [9].
Telltale warning signs include “Execution stopped at this node (n8n may
have run out of memory)” messages, “Allocation failed — JavaScript heap
out of memory” in server logs, and Connection Lost or 503 Service
Temporarily Unavailable responses [9].
To reduce memory consumption: process data in smaller chunks (e.g., 200
rows instead of 10,000), avoid manual executions (n8n duplicates data
for the frontend), and split large workflows into sub-workflows so each
returns only limited output to the parent [9].
For the complete memory tuning and monitoring guide, see the n8n Node Execution Hub.

How do execution timeouts work, and how do they control long-running workflows?

n8n provides two-tier timeout control. The first tier,
EXECUTIONS_TIMEOUT, sets a default timeout in seconds for all
workflows — it defaults to -1 (disabled). When set, n8n
first attempts a soft timeout (waits for the current node
to finish), then kills the process after waiting for a fifth of the given
timeout duration [11].

The second tier, EXECUTIONS_TIMEOUT_MAX, sets the maximum
timeout users can configure per individual workflow — defaulting to
3600 seconds (1 hour) [12].
Example: export EXECUTIONS_TIMEOUT=3600 for a 1-hour default
across all workflows, and export EXECUTIONS_TIMEOUT_MAX=7200
for a 2-hour ceiling on per-workflow overrides. This two-tier system
means the instance admin can enforce a hard global ceiling that no
individual workflow can exceed. Users can override
EXECUTIONS_TIMEOUT in the Settings tab of each individual
workflow up to the EXECUTIONS_TIMEOUT_MAX ceiling. For AI
and LLM nodes (OpenAI, Anthropic, Mistral, Ollama) that may need longer
processing, a separate N8N_AI_TIMEOUT_MAX variable controls
the HTTP request timeout at 3,600,000 ms (1 hour)
default [12].
For complete error handling and retry patterns that catch timeout
failures, see the n8n Error Handling nodes guide.

⚡ Key Timeout Configs:
EXECUTIONS_TIMEOUT = default per-workflow ceiling
(default: -1, disabled). EXECUTIONS_TIMEOUT_MAX =
max per-workflow override (default: 3600 seconds / 1 hour).
N8N_AI_TIMEOUT_MAX = AI node HTTP timeout (default:
3,600,000 ms / 1 hour). Soft timeout fires first (current node
finishes), then hard kill after one-fifth the timeout duration.
[11]

How does the complete regular-mode execution lifecycle go from trigger to data written to database?

In regular mode, the lifecycle begins when a trigger
fires (webhook, schedule, manual). The WorkflowRunner
is the primary entry point that decides between runMainProcess()
and enqueueExecution() based on the
executions.mode configuration [13].
Regular mode takes the runMainProcess() path — executing the
entire workflow in the current Node.js process.

The lifecycle progresses through four phases. Phase 1 — Registration:
ActiveExecutions.add() creates the execution record and
ExecutionRepository.setRunning() marks the start time in the
database. Phase 2 — Engine Invocation:
WorkflowExecute.run() initialises the node execution stack.
Phase 3 — Node Processing: the engine pops each node from
the stack, executes it, captures its output JSON, routes data to downstream
nodes via addNodeToBeExecuted(), and repeats until the stack
empties. Phase 4 — Finalisation: results are written to the
database, binary data to configured storage, and
ActiveExecutions.finalizeExecution() releases the execution
tracking slot [13].
For production deployments above ~200 workflow executions per day, switch to
queue mode to separate the UI from execution and enable horizontal scaling —
the complete production blueprint is available in the Docker Compose production stack guide.

References

This guide is for informational purposes only. For the most current and authoritative information,
always refer to the official n8n website (n8n.io) and
the n8n documentation. Execution modes,
concurrency defaults, and timeout settings may change over time.



Leave a Reply

Your email address will not be published. Required fields are marked *