Conditional verdict: identify the bottleneck before adding a worker
Record the selected image tag, edition and matching release notes before changing topology. Never use mutable latest as a version decision. The captured n8n 3.0 sources conflict: the breaking-change page calls it early access while release notes carry a potentially different channel label. Resolve the selected tag against release notes, migration report and pre-publication check; do not invent a minor version.
| Observed need | Candidate mechanism | Dependency added | Does not solve | Next check |
|---|---|---|---|---|
| Production bursts stall one instance | Regular production cap | Queued work and logs | Excluded classes; Code isolation | Arrival rate, wait age, startup behavior |
| Distribute production execution | Redis queue mode | Redis, shared DB, same key | HA, backup, throughput guarantee | DB, network, binary path, limits |
| Isolate Code nodes | External task runner | Matching version and placement | General workflow distribution | Release guide and security boundary |
| Assistant-generated code | Optional Assistant sandbox | Privileged Docker-in-Docker trust | Queue worker, model or Code runner | Edition and threat boundary |
Four concepts people incorrectly call “queue” or “runner”
Regular-mode production concurrency
Regular mode has no production concurrency limit by default. The documented N8N_CONCURRENCY_PRODUCTION_LIMIT=20 is an example, not a default or recommendation. When set, trigger/webhook production executions are admitted up to the limit and excess work waits FIFO. This limits admission, not execution capacity.
Manual, sub-workflow, error and CLI executions are outside this cap. Queued work cannot be retried; cancelling/deleting removes it. On startup, n8n resumes up to the limit and re-enqueues the rest. Confirm release behavior with owners.
Production trigger → configured limit → execute or FIFO wait. Manual UI, sub-workflow, error and CLI executions bypass this cap; evaluation has a separate limit.
Redis queue-mode workers
Set EXECUTIONS_MODE=queue on main and workers. Main puts execution IDs in Redis; workers read workflow state from the shared database, execute and report through Redis. The caller stays connected to main or the webhook process, so this handoff can add latency.
Workers need the supported shared DB, Redis and main's same instance key. Processes on one VPS share limits and failure domain; another host adds network, recovery and billing work, not HA.
Caller → main/webhook → Redis execution ID → worker ↔ shared database. All required processes need the same instance key; a Code runner sidecar is separate.
External Code-node task runners
Task runners broker Code-node tasks between n8n and a runner process. They are a security and execution boundary for Code tasks; they do not pick general workflow jobs from Redis. Internal runner mode executes under the same user and host boundary as n8n, so a sandbox escape can reach that user's resources. Use the selected release's external-runner design and security guidance when Code isolation is a requirement.
The runner must match the n8n version. The captured runner guide says each queue worker needs its own sidecar. The older documented exception for manual executions on main when manual work is not offloaded must not be carried forward without checking the selected release: n8n 3 changes manual execution behavior on workers. Confirm where manual Code tasks run and which sidecars they require before counting services. Code timeout and memory policy belong in workload acceptance; Article 7 handles AI execution contexts and Article 9 handles runner secrets and hardening.
Assistant sandbox and multi-main are different again
The optional Assistant Docker-in-Docker sandbox supports generated code. It is privileged/root-equivalent, not a workflow worker, Code runner or resident model; do not count it as queue capacity.
Multi-main is also distinct from adding workers. The captured queue guide requires matching n8n versions, shared Postgres and Redis, opt-in configuration and session persistence for multi-main. It is an Enterprise capability. Queue mode is documented as Community; viewing workers in the n8n UI is Enterprise. The optional worker health endpoints are a separate operational probe. Recheck edition and license terms for the selected release before relying on any boundary below.
| Capability | Captured boundary | Verify before design | Cost hand-off |
|---|---|---|---|
| Redis queue mode | Queue mode listed in Community | Selected tag, supported DB and exact edition | Price Redis and DB placement once in Article 2 |
| Multi-main | Enterprise; shared Postgres/Redis, matching version, opt-in and session persistence | License and all topology prerequisites | Record license and selected services; do not infer price |
| UI worker view | Enterprise in captured docs | Current selected edition feature access | Unverified cash value remains unresolved |
| Assistant sandbox | Optional privileged Docker-in-Docker boundary | Whether Assistant feature and sandbox are actually selected | Count only selected host/service and measured terms |
Concurrency precedence and workload classes
Do not add concurrency controls together. In queue mode, non--1 N8N_CONCURRENCY_PRODUCTION_LIMIT takes precedence; otherwise --concurrency applies, falling back to its default. Record the effective value per process. Worker flag default is 10; the guide recommends at least 5. Neither means jobs per host. Low per-worker concurrency across many workers can exhaust DB connections.
Fill this inventory with observed classes and selected-release behavior. Do not infer manual, evaluation or waiting behavior from production triggers.
| Source / class | Regular production cap? | Queue worker path? | Profile and retry question to record | Owner |
|---|---|---|---|---|
| Production trigger or webhook | Yes | Yes in queue mode | Payload, duration, wait; verify failure/retry | Workflow owner |
| Manual UI run | No | Release-dependent; verify n8n 3 | UI data copies; runner placement | Operator + author |
| Sub-workflow | No | Verify caller/version behavior | Nested volume, return payload, cancellation | Workflow owner |
| Error workflow | No | Verify release and trigger path | Failure burst, recursion, notification | Workflow owner |
| CLI-started execution | No | Verify command/deployment path | Initiation and retry expectation | Operator |
| Evaluation run | Separate limit | Verify setting and placement | License tier and test data | Evaluator |
| Waiting / resumed execution | Do not assume | Inspect resume path | Age, persistence, cancellation | Workflow owner |
| Retry queued item | Not supported in captured N11 | Verify release behavior | Document operator response | Operator |
sum(each worker's chosen concurrency) is only a configured parallel-job ceiling signal, not throughput, safe utilization or capacity.
Find the actual constraint with a resource worksheet
Compare equivalent windows before/after, separating observed demand, configured limits and provider allocations. Mark unknowns plainly: worker count hides queue age, execution mix, DB pressure and workflow data memory.
| Observation field | Before-change record | After-change record | Interpretation / owner |
|---|---|---|---|
| Timestamp, window and release/tag | ____ | ____ | Use matching observation windows; operator |
| Active production, manual, sub-workflow and evaluation counts | ____ | ____ | Keep classes distinct; workflow owner |
| Effective production cap and each worker concurrency | ____ | ____ | Record env precedence and command flag; operator |
| Worker count, queued depth and oldest wait age | ____ | ____ | Do not use queue depth alone as throughput; operator |
| DB active/available connections and errors | ____ | ____ | Compare to actual pool/DB limits; DBA/operator |
| Redis health and memory observation | ____ | ____ | Include relay only where applicable; Redis owner |
| Main, worker, runner and host CPU/RAM | ____ | ____ | Record measured window and process mapping; operator |
| Payload, binary and response sizes | ____ | ____ | Separate normal binary from response relay; author |
| Failures, retries, drain and recovery evidence | ____ | ____ | Link trace/receipt without secret values; operator |
Envelope measured demand for main, webhook processors, workers, matching runners, Redis, DB, proxy and selected services, plus operator-set headroom. Do not call hypothetical maxima an average. Keep execution JSON, Code copies, binaries and manual UI copies separate from request counts; they affect memory.
Unknown DB limits, Redis memory, queue age or payload distribution leave sizing incomplete. Reduce admission, bound jobs, observe shared services, stage one worker or revisit topology. Change one thing with a stop threshold; no arithmetic predicts a VPS size.
Choose an operating path
Choose by observed condition, then verify prerequisites. A component helps only if it relieves the measured constraint without exhausting a shared dependency.
| Condition | First candidate | Inventory and observe | Stop/change when | Next link |
|---|---|---|---|---|
| Bounded production burst on regular deployment | Production cap | Production arrival rate, FIFO wait and excluded classes | Manual work or other resources remain unbounded | Runbook acceptance below |
| Manual or heavy data work is the symptom | Classify and bound workflow/data; cap alone will not cover it | Manual copies, Code allocations, payload and duration | Class remains unknown or no owner accepts wait behavior | Article 7 for AI context |
| Distributed production execution with supported state | Redis queue mode | Postgres, Redis, key, binary mode, connections and effective concurrency | SQLite, public unauthenticated service, key mismatch or unsupported storage | Article 4 |
| Code isolation is the need | External Code runner | Matching versions, sidecar placement, trust and resource policy | Runner topology or secret boundary is unclear | Article 9 |
| Very large webhook response | Inspect versioned relay offload | Exact version, shared storage and Redis response budget | Older main, unreadable storage or unsupported binary mode | Article 6 |
| Dedicated webhook processors | Evaluate only with traffic-path requirements | Routing, shared queue port 5678 default, workers and health | Route ownership or main-pool exclusions are unverified | Article 6 |
| Multi-main requirement | Verify Enterprise design prerequisites | Edition, session persistence, versions, Postgres and Redis | Any requirement or recovery behavior is unverified | Article 10 |
| Second host considered | Compare process isolation with placement | Network, key/state, backup, failure domain and duplicate billables | Independent recovery and access paths are not proven | Provider requirements |
A second host adds network and stateful operations; it guarantees neither failover nor recovery. Verify private networking, firewall, backup scope, snapshot/cancellation, renewal, transfer and support at the provider route. Unknowns remain unknown; price selected services with the cost tool.
Change runbook: discover, stage, accept, drain
This bounded acceptance procedure is not an install recipe. It emits no environment values and changes no service. Replace placeholders privately; keep secrets out of shell history, output, tickets and version control.
1. Preconditions and read-only discovery
Identify the owner, selected tag/edition, recovery point, processes and topology. This read-only Bash snippet lists container names, image references and states only. Run on the intended Docker host; non-Docker deployments need an approved inventory method.
#!/usr/bin/env bash
set -euo pipefail
# Read-only inventory. No environment, command, mount, label, or log output.
if ! command -v docker >/dev/null 2>&1; then
printf '%s\n' 'STOP: Docker CLI unavailable; use the deployment owner’s approved inventory.'
exit 2
fi
if ! docker info >/dev/null 2>&1; then
printf '%s\n' 'STOP: Docker daemon is not readable; do not escalate or change access for this check.'
exit 2
fi
printf '%s\n' 'Container inventory: name | image reference | state'
docker ps -a --format '{{.Names}} | {{.Image}} | {{.State}}'
printf '%s\n' 'STOP after inventory. Resolve each image reference to an approved immutable tag/digest in the deployment record.'
Check protected configuration and secret manager without copying values. Record key presence, owner, rotation date and shared delivery result only. Never print environment or unredacted inspect output. Record DB/Redis as private service identifiers, not credentials.
| Discovery field | Record without secret values | Stop if |
|---|---|---|
| Selected n8n tag, release notes, migration report | REPLACE_WITH_REVIEWED_N8N_VERSION; source links; channel status | Tag or 3.0 status/channel conflict unresolved |
| Edition, deployment shape and each process | Main / worker / webhook / runner count and placement | Unknown process owner or incompatible version |
| Effective concurrency | Production variable present? value privately reviewed; worker flag chosen value | Precedence or execution class unclear |
| DB, Redis and key path | Supported DB/version, protected endpoint identifiers, key present and shared? | SQLite distributed queue, public listener, missing/mismatched key |
| Binary and relay behavior | Mode, shared-storage design, selected release, body test plan | Unsupported filesystem assumption or untested offload path |
| Observed resource baseline | Worksheet window, thresholds and data owner | No DB/Redis or resource stop threshold |
2. Recovery gate and design record
Confirm a recoverable backup for DB and artifacts: database, .n8n, key, external binary data and deployment configuration may differ. Check coverage in Article 4 and restore acceptance in Article 10. Do not bundle a major migration.
Complete this operator record before a staged change. Values below are placeholders or operator choices, not recommendations. Store secret values only in the approved secret system; actual .env remains outside version control and logs.
Change ID: REPLACE_WITH_CHANGE_ID
Selected n8n tag/digest: REPLACE_WITH_REVIEWED_N8N_VERSION
Matching release notes + migration report checked by: REPLACE_WITH_OWNER
Chosen path: REPLACE_WITH_REGULAR_CAP_OR_QUEUE_OR_RUNNER
Production cap: REPLACE_WITH_OPERATOR_CHOICE_OR_UNSET
Worker --concurrency: REPLACE_WITH_OPERATOR_CHOICE_OR_NOT_APPLICABLE
Effective precedence reviewed: REPLACE_WITH_YES_NO
Database and Redis private service IDs: REPLACE_WITH_PRIVATE_IDS
Same instance key delivered to required processes: REPLACE_WITH_SECRET_CHECK_RESULT
Binary mode and response relay policy: REPLACE_WITH_REVIEWED_POLICY
Runner version/placement, if selected: REPLACE_WITH_MATCHING_VERSION_AND_MAP
Baseline window / DB and Redis thresholds: REPLACE_WITH_MEASURED_VALUES
Recovery artifact and restore owner: REPLACE_WITH_RECOVERY_RECORD
Admission stop owner / queue cutoff / rollback target: REPLACE_WITH_APPROVED_PLAN
Validate release semantics first. Map matching runner sidecars to required workers and verify manual-run placement. Keep Redis/DB private and authenticated; deliver the same instance key without recording it. Startup order or an open socket does not prove end-to-end readiness.
3. One bounded staged change and acceptance
Change one variable at a time in isolated staging with harmless workflows, using the operator's selected-release procedure.
- Record before measurements for equivalent observation windows. State the expected change: which class should wait, execute, or use a runner, and which shared resource must remain below its operator threshold.
- Apply the reviewed configuration in staging. Confirm all component tags match and required services are private and authenticated. Do not assume startup order proves readiness.
- Verify the intended worker registration or optional health/readiness probe. If health checks are enabled, understand that the endpoints only indicate process and DB/Redis readiness.
- Run a harmless production-trigger workflow plus separate manual, sub-workflow, error and CLI cases only where relevant. Confirm each path matches the selected-release behavior record; check FIFO admission, queued cancellation/retry expectations and restart requeue behavior.
- Verify workflow result persistence and credential decryption through each required process without exposing credential values. Confirm DB connection use, Redis memory, main/worker/runner RAM and CPU remain inside recorded thresholds.
- For response offload, use a non-sensitive test response at a bounded size; verify worker write, main read, client body and cleanup. Test ordinary binary persistence separately. Do not infer one passing path from the other.
- Compare after measurements with the same observation window and record failures, queue age and resource deltas. Accept only if the intended class behaves correctly, dependencies remain healthy and the owner signs the receipt.
Acceptance receipt: selected tag and sources ____; topology/process map ____; class-by-class outcome ____; effective concurrency ____; DB connection peak/threshold ____; Redis memory/threshold ____; main/worker/runner resource window ____; key verification result (no value) ____; binary and response tests ____; result persistence ____; operator and workflow-owner sign-off ____.
4. Drain, stop and rollback branch
No universal drain command or job checkpoint guarantee exists. Before a window, document how this deployment stops admissions, inspects work without deleting it, and decides whether long jobs finish or terminate. Record cutoff and accepted loss. If the selected-release procedure is not rehearsed, stop.
Stop immediately on mismatched versions or keys, public unauthenticated DB/Redis, unexpected retries or lost results, unsupported binary storage, rising DB connection exhaustion, Redis or memory threshold breach, failed key decryption, or inability to account for in-flight work. Keep the last known-good topology and artifacts intact.
- Stop new admissions using the deployment's reviewed operational control; record the time and queue state. Do not improvise a database edit or delete jobs to make the queue appear empty.
- Allow in-flight work to finish only until the approved cutoff and only if its effects are understood. Record remaining work and owners; do not claim graceful shutdown timeout guarantees completion.
- If acceptance fails, restore the prior compatible configuration and component set using the approved change procedure. Restore database and artifacts only from the compatible recovery point if required; never combine a new data format with an old runtime without a verified migration path.
- Before reopening admissions, verify the prior main/worker, DB, Redis, key and binary path; run a harmless representative workflow and confirm result persistence. Reconcile queued and externally triggered work with workflow owners.
- Attach the receipt, unresolved items and exact cutoff to the change record. Send additional host/process/storage requirements to Article 2 and provider terms to the evidence-backed provider route.
This branch links to Article 10 for export, migration and recovery boundaries. Exports are not a substitute for an accepted database-and-artifact restore; do not attach a recovery time or loss guarantee unless your own tested plan supplies it.
Sources and updates
Primary n8n documentation captures checked 2026-11-06. Recheck version-sensitive behavior against the selected tag before changing a deployment.
- n8n: Control concurrency — regular-mode default and class exclusions, FIFO, startup and precedence. Capture checked 2026-11-06.
- n8n: Enable queue mode — Redis/DB flow, worker concurrency, relay, health and multi-main. Capture checked 2026-11-06.
- n8n: Set up task runners — runner boundary and worker sidecars. Capture checked 2026-11-06.
- n8n: Fix memory issues — workflow, Code and manual execution memory. Capture checked 2026-11-06.
- n8n: Self-hosted AI Starter Kit — Assistant sandbox context.
- n8n: Compare editions — feature and license boundaries.
Captures do not establish the current release; resolve the n8n 3.0 status conflict at selection. No deployment, restore, load test, server change, performance check or provider quote was performed. See Methodology.