n8n Node Execution: Run Order, Queue Mode & Concurrency
⚡ n8n Workflow Automation T2 · Node Execution
n8n Node Execution: Run Order, Queue Mode & Concurrency

n8n’s execution system supports two fundamental operational modes that determine how workflows are processed. Regular mode (default) runs everything — API, UI, webhooks, trigger polling, and workflow execution — in a single Node.js process with no Redis dependency, using either SQLite or PostgreSQL, suitable for small deployments and development. Queue mode enables horizontal scaling by distributing workflow executions across multiple worker processes coordinated via Redis, separating the main process (UI/API/webhook reception) from workers (execution), and requiring PostgreSQL because SQLite cannot handle concurrent multi-process writes. A single environment variable — N8N_CONCURRENCY_PRODUCTION_LIMIT — controls production execution concurrency in both modes, overriding per-worker --concurrency flags. [1] [2]

2
Execution Modes (Regular / Queue) [1]
6
Steps in Queue Mode Flow [2]
PostgreSQL
Required for Queue Mode [1]
Redis ≥6.0
Queue Mode Dependency [3]
Dimension Regular Mode Queue Mode
Execution model Single-process: API, UI, webhooks, execution in one Node.js process [3] Distributed: main process handles UI/API/triggers; workers handle execution via Redis [2]
Best for Small deployments, development, testing [2] Production, high-volume, horizontal scaling [2]
Scaling approach Vertical (increase process resources) [2] Horizontal (add worker processes) [2]
Redis required ❌ No [3] ✅ Yes (Redis ≥6.0 + Bull) [3]
Database SQLite or PostgreSQL [2] PostgreSQL (required) [1]
Enabled via Default [3] EXECUTIONS_MODE=queue [1]

How does n8n’s stack-based execution engine process nodes sequentially?

n8n uses a stack-based execution model through the WorkflowExecute class. It initialises a node execution stack containing the trigger node, then processes nodes sequentially via processRunExecutionData(). After each node executes, the engine captures its output JSON and routes data to downstream nodes by calling addNodeToBeExecuted(), maintaining full execution state until every node is complete. [4] [5]

The engine supports two execution orders: v0 (legacy) and v1, configured via the N8N_EXECUTION_ORDER environment variable. The WorkflowRunner class is the primary entry point — it decides between regular in-process execution via runMainProcess() and distributed queue-based execution via enqueueExecution(). The ActiveExecutions service tracks all currently running executions in the process, manages response promises for webhook-triggered workflows, and provides cancellation capabilities. For a complete breakdown of node execution order across parallel branches — where the leftmost branch with the highest y-position executes first, and you can reorder branches in workflow settings via Parallel Branch Execution Order — see the IF & Switch node branching guide.

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

Queue mode splits n8n into three logical process types: the main process handles the editor UI, REST API, and trigger listening (webhooks, schedules, polling); Redis (≥6.0 required) acts as the message broker via the Bull job queue library, holding job descriptions with workflow IDs, trigger data, and credential references; and worker processes continuously poll Redis, grab available jobs, and execute them via WorkflowExecute independently. [2] [3]

The execution follows a precise six-step flow: (1) the main process receives a trigger event and generates a workflow execution; (2) it stores the initial execution record in PostgreSQL; (3) the execution ID is pushed to the Redis Bull queue with workflow metadata; (4) the next available worker picks up the job from the Redis queue; (5) the worker fetches the complete workflow definition and credentials from PostgreSQL using the execution ID; (6) the worker executes the workflow nodes, writes results back to PostgreSQL, and signals completion to Redis [2]. Critically, the main process never executes workflows directly in queue mode — it only enqueues jobs. A fourth optional process type, the webhook processor, can be deployed independently to scale incoming webhook handling. 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 so workers can decrypt credentials stored in PostgreSQL [1]. For the complete production deployment blueprint, see the n8n Docker Compose production stack guide.

Why does queue mode require PostgreSQL, and what happens if you use SQLite?

n8n recommends PostgreSQL 13+ for queue mode. Running queue mode with an SQLite database is not recommended and will cause corruption. The reason is architectural: in queue mode, multiple worker processes must read and write workflow definitions, execution state, and results concurrently. SQLite serializes all writes through a single file-level lock — under concurrent multi-process access, writes queue sequentially, last-write-wins race conditions corrupt execution state, and worker processes encounter “database is locked” errors. [1] [2]

PostgreSQL handles this natively through MVCC (Multi-Version Concurrency Control) with row-level locking — multiple workers can read and write simultaneously without blocking each other. For production deployments, configure DB_TYPE=postgresdb with the required DB_POSTGRESDB_HOST, DB_POSTGRESDB_PORT (default 5432), DB_POSTGRESDB_DATABASE, DB_POSTGRESDB_USER, and DB_POSTGRESDB_PASSWORD variables. For SSL-encrypted connections, set DB_POSTGRESDB_SSL_ENABLED=true. For high- availability PostgreSQL, deploy with primary-replica replication and connection pooling via PgBouncer or the built-in DB_POSTGRESDB_POOL_SIZE setting. The main process writes initial execution records and the workers write results back — both must reach the same database. For the complete database selection guide covering SQLite vs PostgreSQL performance benchmarks and migration procedures, see the n8n Database: SQLite vs PostgreSQL guide.

How does N8N_CONCURRENCY_PRODUCTION_LIMIT control execution concurrency in both modes?

N8N_CONCURRENCY_PRODUCTION_LIMIT is a single environment variable that caps the number of production executions running simultaneously in both regular and queue modes. Its default is -1 (disabled in regular mode). 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. Concurrency control applies only to production executions — those started from webhooks or trigger nodes — not to manual executions or sub-workflow calls. [6] [7]

In regular mode, this variable is the only concurrency gate — without it, n8n imposes no limit on simultaneous production executions, which can thrash the event loop and cause performance degradation. Set it to a reasonable value (e.g., export N8N_CONCURRENCY_PRODUCTION_LIMIT=20) to protect the instance. In queue mode, each worker additionally accepts a --concurrency=N startup flag (default: 10). But if N8N_CONCURRENCY_PRODUCTION_LIMIT is set to any value other than -1, n8n takes the limit from this variable and ignores the per-worker flag entirely. Concurrency less than 5 can lead to an unstable environment — consider setting it to at least 5 for best performance. Executions beyond the limit are held in queue 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. For comprehensive scaling strategies including worker count tuning and horizontal scaling patterns, see the n8n Scaling & Queue Configuration guide.

How do execution timeouts and the execution lifecycle control long-running workflows?

n8n provides two-tier timeout control. EXECUTIONS_TIMEOUT sets a default timeout (in seconds) for all workflows — defaults to -1 (disabled). When a workflow exceeds this duration, n8n attempts a soft timeout first (waits for the current node to finish), then kills the process after waiting for a fifth of the given timeout duration. EXECUTIONS_TIMEOUT_MAX sets the maximum timeout users can configure per individual workflow — defaults to 3600 seconds (1 hour). Example: export EXECUTIONS_TIMEOUT=3600 for a 1-hour default, export EXECUTIONS_TIMEOUT_MAX=7200 for a 2-hour ceiling. [8] [9]

The execution lifecycle is managed by WorkflowRunner and tracked by ActiveExecutions. Production executions — those fired by webhooks or triggers — are the only ones subject to concurrency control. Manual executions (from the editor UI), sub-workflow calls, error executions, and CLI executions (n8n execute --id=N) are exempt. Queued executions cannot be retried — cancelling or deleting a queued execution removes it from the queue. For execution data management, the system provides pruning controls: EXECUTIONS_DATA_MAX_AGE defaults to 336 hours (14 days), and EXECUTIONS_DATA_PRUNE_MAX_COUNT defaults to 10,000 executions retained in the database. For monitoring concurrency, watch logs for executions being added to and released from the queue. For complete error handling and retry patterns that catch timeout failures, see the n8n Error Handling nodes guide.

⚡ Concurrency Quick Reference: (1) Set N8N_CONCURRENCY_PRODUCTION_LIMIT=20 to prevent event-loop thrash. (2) In queue mode, this overrides per-worker --concurrency. (3) Default per-worker concurrency is 10; minimum recommended is 5. (4) Excess executions are queued in FIFO order. (5) Concurrency applies only to production executions — manual and sub-workflow executions are exempt. [6]

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 *