Introduction

A 502 Bad Gateway error from Nginx means the reverse proxy received an invalid response or no response at all from the upstream application server. The most common cause is the downstream application crashing, restarting, or refusing connections. The Nginx error log reveals the root cause:

bash
2026/04/08 18:30:22 [error] 5678#0: *7890 connect() failed (111: Connection refused) while connecting to upstream, client: 10.0.0.5, server: example.com, request: "GET /api/data HTTP/1.1", upstream: "http://127.0.0.1:3000/api/data"

Symptoms

  • Browser displays 502 Bad Gateway page
  • Nginx error log shows "connect() failed (111: Connection refused) while connecting to upstream"
  • Error appears suddenly after application deployment or crash
  • Some requests succeed while others fail (intermittent during restart)
  • Application process may not be running or is binding to the wrong port

Common Causes

  • Application process crashed due to unhandled exception or out-of-memory kill
  • Application restarting after deployment, briefly refusing connections
  • Application listening on wrong address (e.g., IPv6 only while Nginx connects via IPv4)
  • Port conflict preventing the application from binding
  • Upstream server group has no healthy members

Step-by-Step Fix

  1. 1.Check if the upstream application is running:
  2. 2.```bash
  3. 3.systemctl status myapp
  4. 4.ss -tlnp | grep 3000
  5. 5.`
  6. 6.If the process is not running or the port is not bound, the application has crashed.
  7. 7.Review application logs for crash reasons:
  8. 8.```bash
  9. 9.journalctl -u myapp --since "10 minutes ago" --no-pager
  10. 10.`
  11. 11.Look for OOM kills, unhandled exceptions, or port binding errors.
  12. 12.Verify Nginx upstream configuration matches the actual application address:
  13. 13.```nginx
  14. 14.upstream backend {
  15. 15.server 127.0.0.1:3000;
  16. 16.keepalive 32;
  17. 17.}

server { location / { proxy_pass http://backend; proxy_next_upstream error timeout http_502 http_503; proxy_next_upstream_tries 2; proxy_connect_timeout 5s; } } `` The proxy_next_upstream` directive tells Nginx to retry on 502 errors.

  1. 1.Add health check with max_fails to remove crashed backends from rotation:
  2. 2.```nginx
  3. 3.upstream backend {
  4. 4.server 127.0.0.1:3000 max_fails=3 fail_timeout=10s;
  5. 5.server 127.0.0.1:3001 max_fails=3 fail_timeout=10s backup;
  6. 6.}
  7. 7.`
  8. 8.Configure a custom 502 error page for better user experience:
  9. 9.```nginx
  10. 10.error_page 502 /502.html;
  11. 11.location = /502.html {
  12. 12.root /usr/share/nginx/html;
  13. 13.internal;
  14. 14.}
  15. 15.`
  16. 16.Implement graceful restart with zero downtime. For Node.js apps using PM2:
  17. 17.```bash
  18. 18.pm2 reload myapp --update-env
  19. 19.`
  20. 20.For systemd services, use KillSignal=SIGQUIT and TimeoutStopSec=30 in the unit file to allow in-flight requests to complete.

Prevention

  • Use a process manager (PM2, systemd, supervisord) with automatic restart on crash
  • Implement rolling deployments to avoid all instances restarting simultaneously
  • Add application-level health check endpoints (/health) and monitor with uptime tools
  • Configure Nginx proxy_next_upstream for automatic failover to backup servers
  • Set up alerting on 502 error rates using Nginx access log: awk '$9 == "502"' /var/log/nginx/access.log | wc -l
  • Use connection keepalive between Nginx and upstream to reduce connection establishment overhead during restarts