Nginx 502 Bad Gateway With Node.js: Causes and Fixes

Nginx shows 502 Bad Gateway in front of your Node app? Read the error log, then fix connection refused, wrong port, localhost binding, keep-alive, and crashed processes.

A 502 Bad Gateway from nginx means nginx reached your upstream (the Node app) and got no valid response, almost always because the app is down, listening on the wrong host or port, or closing connections nginx expects to reuse; the nginx error log tells you which in one line.

Do not guess. Read the log first.

sudo tail -n 50 /var/log/nginx/error.log

Match the Log Line to the Fix

Log message Meaning Fix
connect() failed (111: Connection refused) while connecting to upstream Nothing listening on that address Start the app, fix port or host
upstream prematurely closed connection while reading response header App crashed or closed mid-request Check app logs for crash, OOM, or unhandled error
recv() failed (104: Connection reset by peer) Upstream reset the socket Keep-alive mismatch or crash; see below
no live upstreams while connecting to upstream All upstream servers marked failed Fix the app, then max_fails and fail_timeout expire
upstream timed out (110: Connection timed out) Too slow, but that is a 504, not a 502 Raise proxy_read_timeout and fix the slow route

Fix 1: App Not Running or Crashing

pm2 status            # or: systemctl status myapp, docker ps
pm2 logs --lines 100

If it keeps restarting, find out why before touching nginx. An out-of-memory kill is common; see Docker exit code 137. Silent crashes from uncaught errors are covered in Node.js production error handling and unhandled promise rejections.

Fix 2: Wrong Port or Wrong Host

location / {
  proxy_pass http://127.0.0.1:3000;
}

Confirm the app is on that port:

ss -ltnp | grep 3000
curl -i http://127.0.0.1:3000/

Inside Docker, an app bound to localhost or 127.0.0.1 is unreachable from other containers. Bind to 0.0.0.0:

app.listen(3000, '0.0.0.0')

Also check that localhost in proxy_pass is not resolving to IPv6 ::1 while your app listens on IPv4 only. Use 127.0.0.1 explicitly.

Fix 3: Keep-Alive Mismatch Causing Intermittent 502s

If 502s are rare, random, and appear after quiet periods, nginx is reusing an upstream connection that Node already closed. Node's default keepAliveTimeout is 5 seconds. Raise it above nginx's upstream keep-alive timeout:

server.keepAliveTimeout = 65_000
server.headersTimeout = 66_000
upstream app {
  server 127.0.0.1:3000;
  keepalive 32;
}
location / {
  proxy_pass http://app;
  proxy_http_version 1.1;
  proxy_set_header Connection "";
}

The same mismatch produces ECONNRESET errors between services.

Fix 4: Pass the Right Headers

Apps behind a proxy need the original host and protocol, or auth cookies and redirects break:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

Missing forwarded headers cause login failures and redirect loops; see NextAuth session null in production and Next.js redirect loops. Large request bodies hit a different nginx limit (413); see Next.js 413 Payload Too Large.

Fix 5: Large Response Headers

Big cookies or headers can trigger upstream sent too big header while reading response header from upstream. Increase proxy_buffer_size and proxy_buffers, and reduce cookie size.

Set Up Alerts So You Hear First

A 502 means users already see an error page. Monitor the status code at the edge, alert on a sustained rate, and add an uptime check as described in how to know when your website is down. Always test config with sudo nginx -t before reloading.

Let Relia Watch Behind the Proxy

Relia monitors your application and servers themselves. When crashes or error spikes cause 502s, it writes the incident up in plain words: what happened, why it thinks so (with a confidence level), and one thing to do next. On request it writes a fix plan with a "Copy for your AI assistant" button; Relia doesn't change code itself, and after you ship it checks the fix against live traffic.

FAQ

What causes 502 Bad Gateway in nginx?

Nginx could not get a valid response from the upstream app, usually because it is down, on the wrong address, or closed the connection.

What is the difference between 502 and 504?

502 means a bad or no response from upstream. 504 means the upstream did not respond before the timeout.

Why do I get 502 only sometimes?

Intermittent 502s usually point to a keep-alive timeout mismatch or a crashing process under load.

All guides