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.