DEVESSENTIALS

HTTP 502 Bad Gateway

A 502 is generated by something in the middle (nginx, a load balancer such as AWS ALB, a CDN such as Cloudflare, an API gateway), not by your application. The proxy tried to forward the request and got nothing usable back: the connection was refused or reset, or the response wasn't valid HTTP.

5xx · Server errorRFC 9110 §15.6.3

502 Bad Gateway

A gateway or proxy received an invalid response from the upstream server it contacted.

Who fixes it: Server. Generated by a proxy, but the cause is the upstream app or the proxy's configuration. Visitors can only retry.

What 502 means

The fix is almost always upstream (the app is down, crashed, or listening on the wrong address) or in the proxy configuration.

Compare with 504: there, the upstream was reachable but didn't answer in time.

Source: RFC 9110 §15.6.3.

Common causes

  • The app isn't running or crashed. nginx logs connect() failed (111: Connection refused) while connecting to upstream.
  • Wrong address or port: the app listens on 3000 but proxy_pass points at 8080, or inside Docker the app binds to 127.0.0.1 and is unreachable from the proxy container. Bind to 0.0.0.0.
  • The app died mid-request (out of memory, killed by the OOM killer, segfault): upstream prematurely closed connection while reading response header from upstream.
  • Keep-alive timeout mismatch: the load balancer reuses an idle connection the app has just closed. Node's server.keepAliveTimeout defaults to 5 seconds and AWS ALB's idle timeout to 60, which causes random, intermittent 502s.
  • Response headers larger than nginx's buffer (big cookies, many Set-Cookie headers): upstream sent too big header while reading response header from upstream.
  • PHP-FPM: wrong socket path or permissions (connect() to unix:/run/php/php8.2-fpm.sock failed (13: Permission denied)), or all workers busy.
  • TLS between proxy and upstream fails: expired or self-signed origin certificate, or SNI not sent. Cloudflare reports origin TLS problems with its own 525 and 526 codes.
  • Vercel: 502: NO_RESPONSE_FROM_FUNCTION when the function returns no response.

How to debug and fix a 502

Check the upstream from the proxy host

If the app doesn't answer directly, nginx isn't the problem.

# Is anything listening on the port?
sudo ss -ltnp | grep 3000

# Does the app answer directly, bypassing nginx?
curl -i http://127.0.0.1:3000/health

# What did nginx see?
sudo tail -n 50 /var/log/nginx/error.log

# Was the process OOM-killed?
sudo dmesg -T | grep -i -E 'killed process|out of memory'

nginx: upstream with keep-alive and bigger header buffers

proxy_buffer_size fixes "upstream sent too big header". Upstream keep-alive requires HTTP/1.1 and an empty Connection header.

upstream app {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;

        proxy_buffer_size 16k;
        proxy_buffers 8 16k;
    }
}

Node.js: outlive the load balancer's idle timeout

The app must keep idle connections open longer than the load balancer does, so the balancer always closes first.

const server = app.listen(3000, '0.0.0.0');

// Longer than the load balancer's idle timeout (AWS ALB default: 60s)
server.keepAliveTimeout = 65_000;
server.headersTimeout = 66_000; // keep above keepAliveTimeout

Restart crashed apps automatically

Run the app under a supervisor (systemd with Restart=always, Docker --restart unless-stopped, PM2, Kubernetes) so a crash is a blip rather than an outage. Then fix the crash.

Headers that matter with 502

Server / Via
Show which hop generated the 502: an nginx error page, server: cloudflare, or awselb/2.0 for an AWS load balancer.
Retry-After
Optional on a 502. Clients should retry idempotent requests with backoff anyway.

502 vs similar status codes

  • 504 Gateway Timeout: The upstream was reachable but too slow. 502 points to a dead or broken upstream, 504 to a slow one.
  • 503 Service Unavailable: A deliberate "not now": maintenance, overload or no healthy backends.
  • 500 Internal Server Error: The app itself responded with an error. With 502 the proxy couldn't get a valid response at all.

SEO impact of 502

Like other 5xx codes, 502s make Googlebot slow down and retry; persistent 502s lead to URLs dropping out of the index. Intermittent 502s (the keep-alive problem) can go unnoticed by people but still show up in Search Console's Crawl Stats.

Related status codes

Looking for another code? Search the full HTTP status codes list, or read which code your API should return in the REST API status codes guide.

Learn more

Browse all developer guides →

Frequently Asked Questions

Is 502 Bad Gateway a problem with my computer?▾

Almost never. A 502 is generated by a server-side proxy or CDN that couldn't get a valid answer from the site's backend. Reloading after a minute is all a visitor can do; the site owner has to fix the backend or proxy.

What is the difference between 502 and 504?▾

Both come from a proxy. 502 means the upstream gave an invalid response or none at all: refused connection, crash, reset. 504 means the upstream was reachable but didn't respond before the proxy's timeout. 502 usually points to a dead or misconfigured app, 504 to a slow one.

Why do I get random 502s behind an AWS load balancer?▾

The classic cause is the app closing idle keep-alive connections before the load balancer does. Set the app's keep-alive timeout higher than the load balancer's idle timeout (60 seconds by default), for example server.keepAliveTimeout = 65000 in Node, with headersTimeout slightly higher still.