
Who this is for: Developers running a self‑hosted n8n instance that gets a steady stream of external HTTP calls (e.g., SaaS integrations, IoT devices) and need guaranteed delivery without data loss. We cover this in detail in the n8n Architectural Failure Modes Guide.
Quick Diagnosis
If your workflow execution time exceeds the incoming request rate, you’ll see 404/500 errors on the sender side or missing entries in the execution log. In production this appears when inbound traffic outpaces what the runner can handle. The quickest fix is to enable n8n’s built‑in backpressure queue and tune maxConcurrency, queueSize, and timeout to suit your traffic.
1. What “Webhook Backpressure” Means in n8n?
If you encounter any inside n8n execution engine resolve them before continuing with the setup.
| Term | n8n Definition | Why It Matters |
|---|---|---|
| Webhook | HTTP endpoint that triggers a workflow when a request arrives. | Entry point for external systems. |
| Backpressure | Throttling of incoming calls when the executor can’t keep up, preventing loss. | Guarantees exact‑once processing under load. |
| Queue | FIFO that stores webhook payloads until the workflow can consume them. | Provides a safety net for traffic spikes. |
Concurrency limit (maxConcurrency) |
Max number of workflow instances that may run in parallel for a webhook. | Controls CPU / memory pressure. |
How it works – Each webhook node creates a listener that pushes the raw request into the execution queue. If the queue is full, the listener returns HTTP 429 (Too Many Requests) – that is the backpressure signal to the caller.
2. Inside n8n’s Queue: From HTTP Request to Workflow Execution
If you encounter any n8n execution ordering guarantees resolve them before continuing with the setup.
2.1 Request Flow (plain‑English)
- Express listener receives the request and validates any signature.
- The request body is serialized (JSON, XML, multipart).
- Serialized payload is placed into the Webhook Queue.
- The Workflow Runner pulls items from the queue, respecting
maxConcurrency. - If the queue exceeds
queueSize, the listener replies with 429 and logs aBackpressureError.
*The queue is where a fast sender meets a slower consumer; you’ll see the 429 right at the edge.*
2.2 Core Queue Check (code snippet)
// src/WorkflowRunner/WebhookQueue.ts – simplified check
if (this.queue.length >= this.getQueueSize()) {
res.status(429).send({
error: 'Webhook queue full – backpressure applied',
});
return;
}
this.queue.push({ payload, headers, requestId });
*The snippet shows the exact point where n8n decides to reject a request because the queue is saturated.*
2.3 Where the Queue Lives
| Deployment | Queue Backend |
|---|---|
| Docker / single‑node | In‑memory (process‑local) |
| Kubernetes / multi‑node | Redis (via n8n-redis plugin) |
| Self‑hosted with DB | PostgreSQL (experimental) |
EEFA note: In‑memory queues disappear on a process crash. For production, always enable a durable backend (Redis) and set
N8N_QUEUE_MODE=redis.
*Switching to Redis is usually faster than chasing edge cases caused by lost in‑memory items.*
3. Configuring Backpressure Settings
If you encounter any n8n state handling between nodes resolve them before continuing with the setup.
All settings are environment variables or UI fields on Workflow Settings → Trigger.
| Variable | Default | Recommended Range |
|---|---|---|
| WEBHOOK_MAX_CONCURRENCY | 5 | 1–20 (depends on CPU cores) |
| WEBHOOK_QUEUE_SIZE | 1000 | 500–5000 for bursty traffic |
| WEBHOOK_TIMEOUT_MS | 30000 (30 s) | 10000–60000 |
| N8N_QUEUE_MODE | memory | redis (production) |
| Variable | Effect |
|---|---|
| WEBHOOK_MAX_CONCURRENCY | Limits parallel workflow instances. |
| WEBHOOK_QUEUE_SIZE | Max items stored before a 429 is returned. |
| WEBHOOK_TIMEOUT_MS | How long a queued request can wait before being dropped. |
| N8N_QUEUE_MODE | Chooses the queue backend (memory vs. Redis). |
3.1 Docker Compose Example (Redis‑backed queue)
Below are two focused snippets: one for the environment block and one for the service definitions.
Environment variables
environment: - N8N_HOST=example.com - N8N_BASIC_AUTH_ACTIVE=true - N8N_BASIC_AUTH_USER=admin - N8N_BASIC_AUTH_PASSWORD=supersecret - N8N_QUEUE_MODE=redis - WEBHOOK_MAX_CONCURRENCY=10 - WEBHOOK_QUEUE_SIZE=3000 - WEBHOOK_TIMEOUT_MS=45000 - REDIS_HOST=redis - REDIS_PORT=6379
Service definitions
services:
n8n:
image: n8nio/n8n
ports:
- "5678:5678"
depends_on:
- redis
redis:
image: redis:7-alpine
restart: unless-stopped
EEFA warning: Setting
WEBHOOK_MAX_CONCURRENCYhigher than the number of CPU cores can cause CPU thrashing and increase latency for all workflows.
4. Monitoring & Troubleshooting Backpressure
4.1 Real‑time Metrics (n8n UI → Settings → Metrics)
| Metric | Description | Alert Threshold |
|---|---|---|
| webhook_queue_length | Current items waiting in the queue | > 0.8 × queueSize |
| webhook_active_workers | Running workflow instances | > maxConcurrency |
| webhook_backpressure_rate | % of requests that received 429 | > 5 % |
4.2 Log snippet for a backpressure event
2026-01-27 14:32:11.123 [error] BackpressureError: Webhook queue full (size=3000) – returning 429 to client 203.0.113.45
4.3 TL;DR – Fix a Sudden Spike
- Check queue length
docker exec n8n curl http://localhost:5678/metrics | grep webhook_queue_length
- If > 80 % of
queueSize, increaseWEBHOOK_QUEUE_SIZEor scale out the n8n workers. - Verify the caller respects 429 and implements exponential back‑off.
4.4 Common Pitfalls
| Symptom | Likely Cause | Fix |
|---|---|---|
| 429 responses even at low traffic | maxConcurrency set too low for CPU |
Raise WEBHOOK_MAX_CONCURRENCY or add more CPU cores. |
| Queue never empties after a burst | Long‑running tasks (e.g., waiting on external API) | Add a Sleep node, split heavy work into sub‑workflows, or use async execution. |
| Lost payloads after a crash | In‑memory queue + process restart | Switch to Redis queue (N8N_QUEUE_MODE=redis). |
5. Production‑Ready Checklist for Webhook Backpressure
- ✅ Enable a durable queue (
N8N_QUEUE_MODE=redis). - ✅ Set
WEBHOOK_MAX_CONCURRENCY≤ CPU cores × 2. - ✅ Tune
WEBHOOK_QUEUE_SIZEto at least 2 × the expected peak burst size. - ✅ Configure HTTP 429 handling on the client side (retry with jitter).
- ✅ Export Prometheus metrics and create alerts for
webhook_queue_lengthandwebhook_backpressure_rate. - ✅ Regularly stress‑test the endpoint with tools like
heyork6to validate thresholds. - ✅ Document SLAs for external partners (e.g., “max 5 retries, 2 s back‑off”).
6. Edge Cases & EEFA (Error‑Handling, Edge‑Cases, Fixes, Advice)
| Edge Case | Why It Happens | Recommended Fix |
|---|---|---|
| Payload > 10 MB (default limit) | Listener rejects before queuing. | Increase N8N_MAX_PAYLOAD_SIZE or use multipart streaming with a custom node. |
| Multiple workflows share the same URL | n8n resolves the first matching workflow, dropping others. | Use unique paths (/webhook/my‑workflow) or enable “Allow Multiple” in node settings. |
| Redis connection loss | Queue becomes unavailable, causing immediate 429 for all calls. | Set REDIS_RECONNECT_TIMEOUT_MS and monitor the redis_up metric. |
| Time‑drift between sender and n8n | Sender retries based on its own clock, causing duplicates. | Enable idempotency key handling (store request IDs in a DB). |
| CPU throttling in containers | Container limits (cpu_quota) lower than required concurrency. |
Adjust cpu_quota or move heavy steps to external micro‑services. |
Conclusion
Enable a durable Redis‑backed queue, size maxConcurrency and queueSize to match your traffic, and watch the built‑in metrics. Doing that guarantees n8n’s webhook endpoint never drops data—even under heavy load. Follow the checklist, respect HTTP 429 on the client side, and your webhook backpressure will work exactly as intended in production.



