Webhook timeouts are one of the most common issues in n8n workflows. This guide covers all timeout scenarios and their solutions.
Understanding Webhook Timeouts
n8n webhooks can timeout at multiple points:
External Service → Reverse Proxy → n8n Webhook → Workflow Processing → Response
↓ ↓ ↓ ↓ ↓
30-60s 60-120s Default Processing Return
timeout timeout 60s timeout time result
Error: 504 Gateway Timeout
Symptom:
504 Gateway Timeout
The server didn't respond in time.
Cause 1: Reverse Proxy Timeout
If using Nginx/Traefik/Caddy in front of n8n:
# Nginx - Increase timeout (nginx.conf)
location / {
proxy_pass http://n8n:5678;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}# Traefik - docker-compose.yml labels
labels:
- "traefik.http.middlewares.n8n-timeout.buffering.maxRequestBodyBytes=50000000"
- "traefik.http.middlewares.n8n-timeout.buffering.maxResponseBodyBytes=50000000"
- "traefik.http.middlewares.n8n-timeout.buffering.retryExpression=IsNetworkError() && Attempts() < 3"# Caddy
reverse_proxy n8n:5678 {
transport http {
dial_timeout 300s
response_header_timeout 300s
}
}
Cause 2: n8n Default Webhook Timeout
# Environment variable to increase n8n webhook timeout
N8N_DEFAULT_WEBHOOK_TIMEOUT=300000 # 5 minutes in millisecondsCause 3: Long-Running Workflow
Split into async pattern:
// Webhook node - Respond Immediately
{
"mode": "responseNode",
"response": {
"status": "accepted",
"jobId": "{{$runId}}"
}
}
// Later in workflow - Use "Respond to Webhook" node
// This sends the actual resultError: ETIMEDOUT / Connection Refused
Symptom:
Error: connect ETIMEDOUT 192.168.1.100:5678
Error: connect ECONNREFUSED 127.0.0.1:5678
Cause 1: n8n Not Running
# Check n8n status
docker ps | grep n8n
# or
systemctl status n8n
# Check logs
docker logs n8n --tail 100Cause 2: Wrong Webhook URL
Verify your webhook URL structure:
# Production URL (with N8N_HOST and N8N_PROTOCOL)
https://your-domain.com/webhook/abc123
# Test URL (different path!)
https://your-domain.com/webhook-test/abc123
# Common mistake - using test URL in production
https://n8n.yourdomain.com/webhook-test/abc123 # ❌ Won't work when workflow inactive
Cause 3: Firewall/Security Group
# Check if port is open
curl -v https://your-n8n-instance.com/webhook/your-webhook-id
# Test from inside container/network
docker exec n8n wget -O- http://localhost:5678/healthzError: Request Entity Too Large
Symptom:
413 Request Entity Too Large
PayloadTooLargeError: request entity too large
Solution:
# Increase payload limit (default is 16MB)
N8N_PAYLOAD_SIZE_MAX=64 # In megabytes
# For file uploads, also set:
WEBHOOK_MAX_UPLOAD_SIZE=64# Nginx configuration
client_max_body_size 64M;Error: Webhook Not Found (404)
Symptom:
404 Not Found
Webhook not found
Cause 1: Workflow Not Active
// Check workflow status via API
fetch('https://your-n8n/api/v1/workflows', {
headers: {
'X-N8N-API-KEY': 'your-api-key'
}
})Activate the workflow in n8n UI or via API.
Cause 2: Using Test vs Production URL
| Mode | URL Path | When to Use |
|------|----------|-------------|
| Test | /webhook-test/ | Development, testing triggers |
| Production | /webhook/ | Live workflows, external integrations |
Cause 3: Webhook ID Changed
When you delete and recreate a webhook node, it gets a new ID. Update all integrations.
Optimizing Webhook Response Time
Pattern 1: Immediate Response + Async Processing
[Webhook] → [Set Response] → [Respond to Webhook] → [Heavy Processing]
↓
Returns immediately
Node configuration:
// Respond to Webhook node
{
"respondWith": "firstIncomingItem",
"responseCode": 202
}Pattern 2: Queue-Based Processing
[Webhook] → [Add to Queue] → [Response: "Queued"]
↓
[Separate Queue Worker Workflow]
Using Redis queue:
// Function node - Add to Redis queue
const redis = require('redis');
const client = redis.createClient(process.env.REDIS_URL);
await client.lPush('webhook-jobs', JSON.stringify({
id: $runId,
payload: $input.all(),
timestamp: Date.now()
}));
return [{ json: { status: 'queued', jobId: $runId } }];Pattern 3: Webhook Timeout with Retry Logic
External service calling your webhook:
// Caller-side retry logic
async function callN8nWebhook(payload, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch('https://n8n.example.com/webhook/xxx', {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' },
signal: AbortSignal.timeout(30000) // 30 second timeout
});
return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i))); // Exponential backoff
}
}
}Docker/Self-Hosted Specific Issues
Memory Limits
# docker-compose.yml
services:
n8n:
image: n8nio/n8n
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 512M
environment:
- NODE_OPTIONS=--max-old-space-size=1536Connection Pooling
# Increase connection limits for high-traffic webhooks
N8N_METRICS=true
N8N_METRICS_PREFIX=n8n_
DB_POSTGRESDB_POOL_SIZE=20Health Check Verification
# docker-compose.yml
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:5678/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30sDebugging Timeout Issues
Enable Verbose Logging
# Environment variables
N8N_LOG_LEVEL=debug
N8N_LOG_OUTPUT=console,file
N8N_LOG_FILE_LOCATION=/home/node/.n8n/logs/n8n.logTrace Webhook Request
# Test webhook with timing
curl -w "@curl-format.txt" -X POST \
-H "Content-Type: application/json" \
-d '{"test": true}' \
https://your-n8n/webhook/your-id
# curl-format.txt contents:
# time_namelookup: %{time_namelookup}s\n
# time_connect: %{time_connect}s\n
# time_appconnect: %{time_appconnect}s\n
# time_pretransfer: %{time_pretransfer}s\n
# time_redirect: %{time_redirect}s\n
# time_starttransfer: %{time_starttransfer}s\n
# ----------\n
# time_total: %{time_total}s\nMonitor Workflow Execution Time
// Code node at start
$workflow.staticData.startTime = Date.now();
return $input.all();
// Code node at end
const duration = Date.now() - $workflow.staticData.startTime;
console.log(`Workflow execution time: ${duration}ms`);
return $input.all();Quick Reference: Timeout Settings
| Component | Environment Variable | Default | Recommended |
|-----------|---------------------|---------|-------------|
| n8n Webhook | N8N_DEFAULT_WEBHOOK_TIMEOUT | 60000ms | 300000ms |
| Nginx | proxy_read_timeout | 60s | 300s |
| Traefik | responseForwarding.flushInterval | 100ms | 100ms |
| Docker | healthcheck.timeout | 30s | 60s |
| HTTP Request Node | Node setting | 300000ms | Workflow-specific |
When to Contact Support
If you've tried everything above and still have timeout issues:
- Collect n8n logs during timeout event
- Note exact timestamp and workflow ID
- Document network topology (proxies, load balancers)
- Capture curl timing output
Our team can help diagnose complex timeout scenarios involving multiple services, custom infrastructure, or high-volume webhook processing.