Nginx

How to Fix "Nginx 502 Bad Gateway" Error With PHP-FPM or Node.js

4 min read by DebuggedIt

Quick answer

Nginx returns a 502 error page instead of your application's response, which means Nginx itself is running fine but couldn't get a valid response from whatever...

Nginx returns a 502 error page instead of your application's response, which means Nginx itself is running fine but couldn't get a valid response from whatever backend it's proxying to β€” PHP-FPM, Node.js, or any other upstream process. The fix depends entirely on why that backend didn't answer, so the Nginx error log is always the right starting point.

The Problem

A request that should hit your application instead returns a generic gateway error:

$ curl -i https://yourapp.com/api/users
HTTP/1.1 502 Bad Gateway

The Nginx error log almost always has more specific detail about what actually failed:

$ tail -20 /var/log/nginx/error.log
2026/08/07 14:22:03 [error] 8821#8821: *142 connect() failed (111: Connection refused)
while connecting to upstream, client: 203.0.113.5, server: yourapp.com,
request: "GET /api/users HTTP/1.1", upstream: "http://127.0.0.1:3000/api/users"

Or, for a PHP-FPM setup using a Unix socket:

2026/08/07 14:22:03 [error] 8821#8821: *142 connect() to unix:/run/php/php8.2-fpm.sock
failed (2: No such file or directory) while connecting to upstream
Where the chain breaks Client Nginx connect() fails PHP-FPM / Node.js crashed, wrong socket, or down Nginx returns 502 the moment upstream refuses the connection

Why It Happens

A 502 always means Nginx successfully acted as a proxy but got a broken or refused connection from the backend it was told to forward to. The most common causes:

  • The backend process isn't running β€” PHP-FPM or Node.js crashed, was never started, or is still restarting after a deploy.
  • Socket or port mismatch β€” Nginx's fastcgi_pass or proxy_pass directive points at a Unix socket path or TCP port that doesn't match what the backend is actually listening on.
  • The backend crashed mid-request β€” an unhandled exception, an out-of-memory kill, or a PHP fatal error that terminates the FPM worker process abruptly.
  • Backend timeout shorter than expected β€” the upstream took too long and Nginx (or the backend's own internal timeout) gave up, closing the connection before a response was ready.
  • Too many simultaneous requests exhausting the backend's worker pool β€” PHP-FPM has a fixed number of worker processes, and once they're all busy, new connections get refused rather than queued indefinitely.

The Fix

Start by confirming the backend process is actually running:

systemctl status php8.2-fpm
systemctl status myapp   # for a Node.js service managed by systemd

If it's down, start it and check its own logs for why it crashed in the first place:

sudo systemctl start php8.2-fpm
journalctl -u php8.2-fpm --since "10 minutes ago"

Verify the socket or port Nginx is configured to use actually matches what the backend is listening on:

cat /etc/nginx/sites-enabled/yourapp
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
ls -la /run/php/php8.2-fpm.sock

If the socket file doesn't exist at that exact path, check what PHP-FPM's pool config actually uses:

grep listen /etc/php/8.2/fpm/pool.d/www.conf

Align both to point at the same socket or port. For a Node.js backend behind a reverse proxy, confirm the port matches too:

location / {
    proxy_pass http://127.0.0.1:3000;
}
netstat -tlnp | grep 3000

If the backend is legitimately being overwhelmed, increase PHP-FPM's worker pool size (balanced against available RAM) so more concurrent requests can be handled:

; /etc/php/8.2/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15

Restart the pool after any config change:

sudo systemctl restart php8.2-fpm

Still Not Working?

If the backend is running, the socket path matches, and it still fails intermittently under load, check whether the backend is crashing on specific requests rather than being down entirely β€” tail its application-level logs while reproducing the failing request, since PHP-FPM and Node.js both log fatal errors that Nginx's error log won't show:

tail -f /var/log/php8.2-fpm.log
# or for Node.js managed by pm2
pm2 logs myapp --lines 50

A pattern of crashes correlating with a specific endpoint or payload usually points at an application bug rather than an infrastructure misconfiguration, and fixing that bug is the real resolution rather than continuing to adjust Nginx or PHP-FPM settings.