HTTP status code · Server errors (5xx)
502 Bad Gateway
502 Bad Gateway means a server acting as a proxy or gateway, such as nginx, a load balancer or a CDN, got an invalid response from the upstream server it forwarded your request to. The most common cause is that the application behind the proxy is down, crashed mid-request or is listening on a different port than the proxy expects.
| Class | 5xx, Server errors |
|---|---|
| Defined in | RFC 9110 §15.6.3 |
| Cacheable by default | Only with explicit Cache-Control or Expires |
| Safe to retry | Yes for GET and other idempotent requests, with backoff; the upstream is often back within seconds |
| Relevant headers |
|
What 502 means
RFC 9110, section 15.6.3, defines 502 as a gateway or proxy receiving an invalid response from an inbound server it accessed while trying to fulfill the request. In practice "invalid" covers several failures: the connection was refused, the upstream closed it before sending a complete response, or it sent headers the proxy could not parse or buffer.
The server that returns the 502 is not the one with the problem. The Server header tells you who is talking: "nginx" means your reverse proxy could not get a good answer from the app, "awselb/2.0" means an AWS load balancer could not, and "cloudflare" means the CDN could not reach or understand your origin. Fix the layer behind the one that answered.
Each proxy draws the line between 502 and 504 a little differently. nginx returns 502 when the upstream refuses or drops the connection and 504 when it times out. Go's httputil.ReverseProxy returns 502 for every upstream error, timeouts included, unless you install your own ErrorHandler.
Common causes
If you are visiting the site
- The site's application server is down or restarting, often during a deploy, while its proxy or CDN is still up and answering.
- A traffic spike crashed or exhausted the backend.
- Rarely, a proxy, VPN or antivirus on your own network that intercepts HTTPS and fails to talk to the site.
If you run the server
- The app process is not running or listens on a different port or socket: nginx logs "connect() failed (111: Connection refused) while connecting to upstream".
- The app crashed or was killed (out of memory, unhandled rejection) mid-response: nginx logs "upstream prematurely closed connection while reading response header from upstream".
- Keep-alive mismatch behind a load balancer: the app closes idle connections sooner than the balancer does (Node.js defaults keepAliveTimeout to 5 seconds, an AWS ALB to a 60-second idle timeout), so the balancer reuses a dead connection and gets a reset.
- Response headers larger than the proxy buffer, typically big cookies or long auth headers: nginx logs "upstream sent too big header while reading response header from upstream".
- PHP-FPM, Gunicorn or uWSGI out of workers, or its socket path in the nginx config does not match the one the process created.
How to fix it
If you are visiting the site
- Wait a minute and reload. Most 502s are a backend restarting, and they clear up on their own.
- Check the site's status page or a service such as Downdetector to see if others are affected.
- If only you get it, try another network or turn off your VPN or proxy for a moment.
If you run the server
- Read the proxy error log first (tail /var/log/nginx/error.log); the message after the timestamp tells you whether the connection was refused, dropped or had oversized headers.
- Hit the app directly from the proxy host, bypassing the proxy (curl -sI http://127.0.0.1:3000/). If that fails, the problem is the app or its port, not nginx.
- Check that the app is running and restarted by a supervisor (systemd, Docker restart policy, PM2), and read its own logs for the crash or out-of-memory kill.
- Behind an AWS ALB or similar, set the app keep-alive timeout above the balancer idle timeout, for Node: server.keepAliveTimeout = 65_000.
- For oversized headers, raise proxy_buffer_size and proxy_buffers in nginx, or shrink the cookies the app sets.
How to send 502
Applications almost never send 502 themselves; the proxy generates it. The examples configure nginx so 502s are rarer and show how to find which hop failed. Only a gateway you write yourself should answer 502 when its upstream misbehaves.
upstream app {
server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Connection "";
# "upstream sent too big header" is answered with 502
proxy_buffer_size 16k;
proxy_buffers 8 16k;
}
# Your own page for 502, status unchanged
error_page 502 /502.html;
}# Which layer answered? The Server header says
curl -sI https://example.com/ | grep -iE '^(HTTP|server)'
# Is the app itself up? Call it without the proxy
curl -sI http://127.0.0.1:3000/
# What nginx saw
grep -E 'upstream|connect\(\)' /var/log/nginx/error.log | tail -n 20Commonly confused with
- 502 vs 504
- 502 means the upstream answered badly or hung up; 504 means it did not answer before the proxy gave up waiting.
- 502 vs 500
- A 500 comes from the application itself; a 502 comes from the proxy in front of it and means the application could not deliver any valid response.
- 502 vs 503
- A 503 says the service is knowingly unavailable, for maintenance or overload; a 502 says the proxy tried and got garbage or a dropped connection.
- 502 vs 520
- Cloudflare uses 520 when your origin returned something empty or unexpected, and its own branded 502 page for failures inside Cloudflare's network.
Frequently asked questions
- Is a 502 Bad Gateway error on my side or the website's?
- Almost always the website's. Something between the site's front door (its proxy or CDN) and its application failed. The exceptions are a corporate proxy, VPN or security software on your network that sits in the middle of HTTPS traffic.
- How long does a 502 error last?
- If it comes from a deploy or a restart, seconds to a couple of minutes. If the application crashed and nothing restarts it, it lasts until someone fixes the server, which is why process supervisors and health checks matter.
- Why do I get intermittent 502s behind a load balancer?
- The classic cause is keep-alive: the application closes idle connections before the load balancer does, and the balancer sends a request on a connection that is already closing. Make the application keep-alive timeout longer than the balancer idle timeout.
- What is the difference between 502 and 504?
- Both come from a proxy. 502 means the upstream sent an invalid response or dropped the connection; 504 means the upstream did not respond in time. With nginx, a refused connection is a 502 and hitting proxy_read_timeout (60 seconds by default) is a 504.
- Does clearing the cache fix a 502 error?
- Rarely. The failure is on the server path, so clearing the browser cache or cookies does not change it. Reloading after a short wait, or trying another network if only you are affected, is more useful.
Last reviewed by Arielton Oberek.