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 *