Why n8n Workflows Return 502 Errors Under Concurrent Load (And the Reverse Proxy Settings That Fix It)

Mike Holownych
#n8n#automation
Share:

Quick Answer

n8n workflows return 502 errors under concurrent load because the reverse proxy in front of n8n is left on its out-of-the-box defaults, which are tuned for low-traffic sites, not a webhook receiver taking bursts of concurrent requests. The settings that typically need to change: connection limits (worker_connections), proxy timeouts (proxy_connect_timeout, proxy_send_timeout, proxy_read_timeout), request buffer sizes (proxy_buffer_size), and connection pooling to the upstream (keepalive). None of these are n8n-specific — they’re standard Nginx production-hardening settings that most default configs skip.

Why ‘Working’ n8n Workflows Start Rejecting Requests Under Real Traffic

A workflow that handles a handful of test webhooks perfectly can start returning 502s the moment real traffic arrives in bursts — a product launch, a marketing send, a retry storm from an upstream service. The workflow logic hasn’t changed. What’s different is concurrency: several webhook deliveries arriving close together, each holding open a connection to n8n while it processes.

The mechanism: each n8n webhook request typically holds open more than one connection to the backend (the initial request plus, depending on your workflow, outbound HTTP calls it makes). Nginx’s default worker_connections value (check your own nginx.conf — common out-of-the-box values are in the 512–1024 range depending on distro and version) sets a hard ceiling on how many connections a worker process can hold open at once. Once you’re near that ceiling, Nginx starts refusing or dropping new connections instead of queuing them, and the client sees a 502 or 504.

This rarely shows up in development, where you’re sending a few test webhooks manually rather than dozens arriving within seconds of each other.

The Reverse Proxy Bottleneck: Default Configs Aren’t Built for Webhook Bursts

The configuration most reverse-proxy tutorials hand you is minimal:

location / {
    proxy_pass http://localhost:5678;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

That’s enough to get n8n working behind Nginx. It is not enough for production webhook volume, for a few concrete reasons:

  1. Short timeout ceilings. Default proxy_connect_timeout/proxy_send_timeout/proxy_read_timeout values (60 seconds on a stock Nginx install) are shorter than some legitimate n8n workflows need — a sync against a slow third-party API, or a workflow processing a large batch, can genuinely take longer than a minute.
  2. No connection pooling to the upstream. Without an upstream block and keepalive, Nginx opens a fresh TCP connection to n8n for every request instead of reusing one. Under load, that adds real overhead and exhausts ephemeral ports faster than necessary.
  3. Small proxy buffers. The default proxy_buffer_size is small relative to the JSON payloads some webhook senders (payment processors, e-commerce platforms) actually send. An undersized buffer on a large payload is a real, if less common, source of 502s.
  4. No upstream health awareness. If n8n restarts — a deploy, a crash, an OOM kill — Nginx keeps forwarding requests to it during the restart window and returns 502s instead of retrying against a healthy instance, unless you’ve configured proxy_next_upstream.

Production-Ready Proxy Settings

The four changes below address each of those points. Adjust the specific values to your own traffic pattern and hardware rather than copying them verbatim.

1. Raise Connection Limits

events {
    worker_connections 4096;  # raise from your distro's default
    use epoll;                # Linux; check the directive your OS's Nginx build supports
    multi_accept on;
}

2. Configure Production Timeouts

http {
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 16 8k;
    proxy_busy_buffers_size 16k;
}

Set these to match your slowest legitimate workflow, not an arbitrary round number — a 300-second ceiling is a reasonable starting point, not a universal correct value.

3. Pool Connections to n8n

upstream n8n_backend {
    server localhost:5678;
    keepalive 32;
    keepalive_requests 1000;
    keepalive_timeout 60s;
}

location / {
    proxy_pass http://n8n_backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

4. Retry Against a Healthy Upstream on Failure

location / {
    proxy_next_upstream error timeout http_502 http_503 http_504;
    proxy_next_upstream_tries 3;
    proxy_next_upstream_timeout 10s;
}

Apply the changes, validate the config (nginx -t), then reload (sudo systemctl reload nginx — a reload, not a restart, avoids dropping in-flight connections). Test under a realistic concurrent load before trusting it against production traffic.

Two Config Mistakes That Compound the Problem

Relying on Docker’s default bridge networking for high-frequency webhook traffic. Docker’s default bridge network adds measurable per-request latency and its own connection-tracking limits. If Nginx and n8n are both containerized and taking meaningful webhook volume, network_mode: host (or a well-tuned bridge network with connection tracking sized for your load) removes a layer of overhead that a default bridge setup doesn’t account for.

Trusting a managed cloud load balancer’s defaults without checking its own timeout ceiling. Cloudflare, AWS ALB, and similar managed proxies have their own idle- and request-timeout limits sitting in front of your own Nginx config — check your specific plan/tier’s documented limits rather than assuming they match what you’ve set at the Nginx layer, since a mismatch there produces the same symptom (502/504) even after the Nginx-level fixes above are in place.

MH

About Mike Holownych

Building AI Syndicate—governance infrastructure for AI agents in regulated environments. 20+ years enterprise operations, now applying that reliability discipline to AI deployment.