
n8n is a workflow automation tool that looks simple on the surface. But the execution model doesn't match the visual model — and that gap causes problems.
n8n lets you build automations by connecting nodes on a visual canvas. Drag, drop, connect. It looks like data flows through your workflow in parallel, left to right.
It doesn’t work that way.
I read n8n’s source code to understand why some workflows break in weird ways. (There are also engineering limitations you should know about.) Here’s what actually matters.
The Editor is Just a Design Tool
The canvas in your browser is just for designing. When you click “Execute,” it packages your workflow as JSON and sends it to the server. The server runs everything. The editor just polls for results.
Why this matters: That “test” button is making a real server request. If your server is slow or overloaded, the editor feels slow — even though nothing’s wrong with your browser.
Nodes Run Sequentially, Not in Parallel
Your workflow might look parallel on the canvas, but execution is sequential. Node A finishes completely before Node B starts.
flowchart LR
A([A runs]) --> B([A finishes]) --> C([B runs]) --> D([B finishes]) --> E([C runs])
classDef default fill:#dbeafe,stroke:#3b82f6,color:#1e40af,stroke-width:2px
The engine walks your workflow like a checklist. It won’t start a node until all its inputs are ready.
Why this matters: A slow API call in Node 3 blocks everything after it. If you have independent operations, they still wait in line. The only way to get true parallelism is the SplitInBatches node, which creates separate execution branches.
Each Item Runs Separately
This is the biggest surprise for most people.
If 100 leads come into an HTTP Request node, n8n doesn’t batch them into one API call. It makes 100 separate calls — one per lead.
| What You Might Expect | What Actually Happens |
|---|---|
| 100 leads → 1 API call with array | 100 leads → 100 API calls |
| Batch processing | Item-by-item processing |
| Fails together | Each item succeeds or fails independently |
Why this matters:
- Rate limits hit fast. 100 leads = 100 API calls = you’re throttled.
- One bad email doesn’t kill the batch. Item 47 can fail while 1-46 and 48-100 succeed.
- Slow nodes multiply. A 200ms API call × 100 items = 20 seconds.
If you need true batching, use a Code node to aggregate items first.
Data Passes by Reference
No subprocesses. No serialization between nodes. When Node A finishes, its output object gets passed directly to Node B.
// Node A returns:
[{ json: { email: "[email protected]", score: 85 } }]
// Node B receives that exact object
// Access it with:
items[0].json.email // → "[email protected]"
The $json you reference in expressions? That’s literally items[currentIndex].json.
Why this matters:
- Nodes share memory. You can pass large objects without performance penalty.
- Mutations are dangerous. If Node B modifies
$json.email, Node C sees the modified version. Clone data if you need the original. - Binary data (files, images) is handled separately — stored by reference, not copied.
Expressions Evaluate at Runtime
When you write {{ $json.email }}, that string sits in your workflow JSON until execution. The server evaluates it when the node runs.
The expression sandbox includes:
$json— current item$input.first()/$input.last()/$input.all()— access other items$node["NodeName"].json— grab output from a specific upstream node$env— environment variables- Standard JS:
.map(),.filter(),.toUpperCase(), ternaries
Why this matters: The preview in the editor uses sample data. If your real data has different shape (missing fields, different types), expressions fail at runtime — not design time. Test with real data.
Active Workflows Consume Resources
When you toggle a workflow “active,” n8n:
- Registers webhook URLs (they stay registered until you deactivate)
- Starts timers for schedules
- Runs polling checks on intervals
These listeners run whether or not they receive data.
| Scenario | Resource Cost |
|---|---|
| 50 active workflows with webhooks | 50 registered URLs, 50 event listeners |
| 20 polling workflows at 5-min intervals | 240 polling operations per hour |
Why this matters: “I’ll just leave it active” has a cost. Unused active workflows waste server resources and slow down workflows you actually need. Deactivate what you’re not using.
The Database Stores Everything
Every execution — inputs, outputs, errors — gets written to the database. Every node’s result. Every retry.
At low volume, this is fine. At high volume, it’s your bottleneck.
Why this matters:
- Execution history fills up fast. 1,000 executions/day × 10 nodes × 30 days = 300,000 records.
- Database performance affects UI responsiveness.
- Prune old executions. Check Settings → Workflow → “Delete executions older than.”
Workers Scale Throughput, Not Isolation
n8n’s queue mode runs workers as separate processes that pull jobs from Redis. This is for handling more concurrent workflows, not for isolating failures.
flowchart LR
A([Main Server]) --> B([Redis Queue]) --> C([Workers])
classDef default fill:#dbeafe,stroke:#3b82f6,color:#1e40af,stroke-width:2px
A worker picks up a job, runs the entire workflow, stores results. If the worker crashes mid-execution, the job returns to the queue and another worker retries.
Why this matters:
- Single-server n8n handles ~50-100 concurrent executions comfortably
- Beyond that, add workers. Each handles 10 concurrent jobs by default.
- Workers are stateless. Any worker can run any workflow. Don’t store anything locally.
What To Do About It
| Reality | What To Do |
|---|---|
| Sequential execution | Put slow operations at the end, or use SplitInBatches |
| Item-by-item processing | Add delays between items for rate-limited APIs |
| Shared memory | Clone objects if you need to preserve original data |
| Runtime expression evaluation | Test with production-like data, not just the happy path |
| Database stores all results | Configure execution pruning before you hit scale |
| Active workflows consume resources | Deactivate unused workflows |
The visual canvas makes n8n approachable. But it hides these mechanics. A workflow that looks clean can still be slow, memory-hungry, or hitting rate limits — because the execution model doesn’t match the visual model. Understanding this is why error handling patterns matter so much. And why some teams are asking whether workflows themselves are becoming obsolete.
There’s a simpler way. OpenClaw replaces workflow graphs with a single AI agent — no nodes, no sequential execution, no rate limit headaches. Compare hosting options.
