Halloween offer: 50 % off your first year Ends in 27d 17h 28m Start free trial

Guides 6 min read

502 Bad Gateway: What It Means and How to Fix It

A 502 Bad Gateway means a proxy, load balancer or CDN got no valid answer from the server behind it. How to find which layer failed, fix the usual causes and catch the next 502 before customers do.

A 502 Bad Gateway error means a server acting as a gateway or proxy got an invalid response from the server behind it. The visitor reached something, usually nginx, Apache, a load balancer or a CDN, but that layer could not get a proper answer from your application. The application crashed, is restarting, is listening somewhere else, or closed the connection halfway through.

That makes a 502 a message about two servers, not one. This guide shows how to tell which layer returned it, how to fix the usual causes and how to hear about the next 502 before your customers do.

What a 502 tells you

Most websites have at least two layers between the visitor and the code. A CDN or load balancer sits in front, a web server such as nginx terminates the connection, and an application process, such as PHP-FPM, Node.js, Gunicorn or a Java server, builds the page. Each layer forwards the request to the next one and passes the answer back.

A 502 appears when one of those layers forwards a request and gets nothing usable back. Compare it with the other gateway errors:

  • 502 Bad Gateway: the upstream server answered with something invalid, reset the connection or refused it.
  • 503 Service Unavailable: the service is overloaded, in maintenance or has no healthy server to send the request to.
  • 504 Gateway Timeout: the upstream server did not answer in time.

So a 502 usually means broken or not running, a 504 usually means slow. Our HTTP status codes cheat sheet lists the rest of the family, and the guide to 503 errors covers overload and maintenance.

Find the layer that returned the 502

Before changing anything, find out who answered. The error page and the response headers usually say it outright:

curl -sI https://www.example.com/checkout
HTTP/2 502
server: cloudflare
cf-ray: 8d2f1c3a5b7e4a21-ARN
  • server: cloudflare with a Cloudflare error page naming your host: Cloudflare reached your origin, and the origin failed.
  • server: nginx or Apache with a plain error page: your own web server could not reach the application behind it.
  • server: awselb/2.0 or another load balancer: the load balancer got no valid answer from any target, or from the one it picked.

Then compare with a request that skips the outer layer. Send it straight to the origin or to the application port on the server itself:

curl -sI --resolve www.example.com:443:203.0.113.10 https://www.example.com/checkout
curl -sI http://127.0.0.1:3000/checkout

If the application answers locally but not through the proxy, look at the proxy’s configuration. If it doesn’t answer locally either, the application is the problem.

Common causes and how to fix them

The application process crashed or is restarting

The most common cause. The process behind the proxy ran out of memory, hit an unhandled exception or was killed, and the proxy has nothing to talk to. nginx logs it plainly:

connect() failed (111: Connection refused) while connecting to upstream,
upstream: "http://127.0.0.1:3000/checkout"

Check whether the process runs and why it stopped:

systemctl status myapp
journalctl -u myapp --since "30 min ago"
dmesg -T | grep -i "killed process"

A line from the kernel’s out-of-memory killer means the server ran out of memory. Restarting brings the site back, but the real fix is more memory, fewer workers or a leak found and fixed. Make sure the service restarts on its own after a crash, for example with Restart=on-failure in its systemd unit.

PHP-FPM is down or out of workers

On PHP sites, nginx passes requests to PHP-FPM through a socket or port. If PHP-FPM is stopped, the socket path is wrong or the socket’s permissions keep nginx out, every PHP page returns 502:

connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory)

That message usually follows a PHP upgrade: nginx still points at the old version’s socket. Point fastcgi_pass at the new socket and reload nginx. If the log instead says server reached pm.max_children, every worker is busy, often waiting for a slow database or an external API. Raise the limit only if the server has memory to spare; otherwise find what keeps the workers busy.

Wrong upstream address or port

After a migration, a container rebuild or a change of port, the proxy may still forward to the old address. The error log shows the address it tried. Compare it with where the application actually listens:

ss -ltnp | grep -E ':(3000|8000|9000)'

In Docker and Kubernetes, the cause is often a service name that no longer resolves, a container listening on 127.0.0.1 inside the container instead of 0.0.0.0, or a readiness check that marks every pod as unready.

The upstream closed the connection early

upstream prematurely closed connection while reading response header means the application accepted the request and then hung up. Typical reasons are a crash halfway through the request, a worker killed for exceeding its own time limit, such as Gunicorn’s --timeout or PHP’s max_execution_time, and keep-alive connections the application closes sooner than the proxy expects. Align the timeouts so the proxy waits a little longer than the application, never the other way round, and look at which requests are slow enough to hit the limit.

Response headers too large

Large cookies or many Set-Cookie headers can be bigger than nginx’s buffer for the upstream’s response headers. nginx then logs upstream sent too big header while reading response header from upstream and returns 502. Raise the buffers carefully:

proxy_buffer_size 16k;
proxy_buffers 8 16k;
# for PHP-FPM
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;

Then find out why the headers grew. A cookie that grows on every visit is a bug worth fixing.

The CDN cannot talk to your origin

When a CDN or load balancer returns 502, check what sits between it and your server. A firewall that blocks the CDN’s address ranges, an origin certificate the CDN does not accept, an origin that only speaks HTTP/1.0 or closes connections too eagerly, or a DNS record pointing at an old server all end the same way. Test the origin directly, as shown above, and check the firewall and the TLS settings on both sides.

502s during deploys

If 502s show up for ten or twenty seconds at a time and always around a release, the deploy itself causes them. The old process stops, the new one takes a few seconds to start, and every request in between fails. The fix is a release order where something is always ready to answer:

  1. Start the new version next to the old one.
  2. Wait until its health check passes. Our guide to building a health check endpoint shows what that check should test.
  3. Switch traffic to the new version.
  4. Let the old version finish the requests it has, then stop it.

Process managers and orchestrators support this as rolling or zero-downtime reloads. Use them rather than a plain restart.

How monitoring catches 502s

A 502 is often short. A deploy causes twenty seconds of errors, a worker crashes and restarts, a cache hides the problem for most visitors. By the time someone opens the site it works again, but a customer in the middle of checkout saw the error.

An uptime monitor requests your pages on a schedule and records the status code and response time of every check. A 502 is a failed check. What matters is what happens next:

  1. Confirm the failure. A single failed request can be a blip. Uptimecheck checks every minute from Stockholm, Sweden, and confirms every failure with a second check before an incident opens, so a one-off reset doesn’t wake anyone up.
  2. Show the evidence. The incident carries the failing response, so you see the status code, the server header and the error page, and a screenshot of what visitors saw. When the server did not answer at all, you get the network path instead.
  3. Reach the right people. Alerts go to email, Slack, Microsoft Teams, PagerDuty, webhooks and the other alert channels your team uses.

Watch more than the homepage. The homepage is often cached by a CDN and keeps working while checkout, login and the API return 502. Add uptime monitors for the pages that earn money and API monitors for the endpoints your apps call. When the 502 comes from an application that ran out of memory, server monitoring shows the memory curve next to the outage.

502 checklist

  1. Read the server header and the error page to see which layer returned the 502.
  2. Request the origin and the application port directly to narrow it down.
  3. Read the proxy’s error log for the same timestamp: refused, closed early or too big header.
  4. Check that the application process runs, and why it stopped if it didn’t.
  5. Compare the upstream address, socket and port with where the application listens.
  6. Align timeouts so the proxy waits longer than the application.
  7. Deploy by starting the new version before stopping the old one.
  8. Monitor key pages and endpoints every minute and confirm every failure before alerting.

Questions

Is a 502 error my fault or the visitor's?

It is on the server side. A 502 means a gateway, such as nginx, a load balancer or a CDN, could not get a valid answer from the server behind it. Clearing the browser cache rarely helps; the fix is on the server.

What is the difference between a 502 and a 504?

A 502 means the server behind the proxy answered with something invalid or closed the connection. A 504 means it did not answer at all within the proxy's time limit. Both point at the upstream server, but a 504 usually means slow, a 502 usually means broken or not running.

Why do I see a 502 only for a few seconds after a deploy?

The old application process stops before the new one accepts connections, so the proxy has nothing to forward to. Start the new process first, wait until its health check passes, then stop the old one.

Does a 502 hurt SEO?

A short 502 does little harm. If search engines keep seeing 5xx errors for hours or days, they crawl less and may drop pages. Fix recurring 502s and use 503 with Retry-After for planned maintenance.

Can Cloudflare cause a 502?

Cloudflare shows a 502 when your origin server returns an invalid response or closes the connection. If the error page is Cloudflare-branded and names your host as the failing part, the problem is at your origin, not at Cloudflare.

Keep reading

Guides 6 min read

504 Gateway Timeout: What It Means and How to Fix It

A 504 Gateway Timeout means a proxy waited for the server behind it and gave up. How to find the slow part, fix it instead of just raising timeouts, and see slowdowns before they turn into 504s.

Read

Guides 5 min read

500 Internal Server Error: How to Find and Fix the Cause

A 500 Internal Server Error means the application failed while handling the request. Where to find the real error message, the causes behind most 500s and how to make sure you hear about them first.

Read

Guides 7 min read

How to Build a Health Check Endpoint (and Monitor It)

A health check endpoint tells monitors and load balancers whether your app can serve requests. What to check, how to keep it fast and safe, code for Laravel, Express and Flask, and how to monitor it.

Read

Downtime is obsolete.

Set up your first monitor in under a minute, or look around the live demo first.

14-day free trial · No credit card required

Start free trial