In this guide 6 sections
A 502 means Nginx reached for your application and got nothing usable back. Read the error log first. It names the upstream and the reason: connection refused, no such socket, reset by peer or a bad header. Then check the app process, the port or socket in the config, and the proxy timeouts.
Start with the error log, not the browser
The browser only says 502. The Nginx error log says why. On most Linux servers it sits at /var/log/nginx/error.log. Run tail -f on it, reload the page and read the line that appears.
That line carries the upstream address and a reason in brackets. Connection refused, No such file or directory, Connection reset by peer and upstream sent too big header each point to a different fix. Guessing before reading wastes an afternoon. Read first.
- connect() failed (111: Connection refused) means nothing is listening
- No such file or directory on a unix socket means a wrong path
- upstream prematurely closed connection means the app crashed mid request
- upstream sent too big header means buffer limits
Check that the app process is alive
Often the application is simply down. Ask the process manager. Run systemctl status for the service, or pm2 list if the app runs under PM2, or docker ps for a container.
Look at why it stopped. Never skip this. An out of memory kill leaves a trace in journalctl and dmesg. A crash on boot, often a missing environment variable after a deploy, shows in the application log.
Restart it. Then watch whether it stays up for an hour, since a service that restarts every few minutes produces intermittent 502s that vanish by the time you look..
Match the port or socket in the config
Open the server block and find proxy_pass or fastcgi_pass. The address there must be the one the app listens on. A deploy that moved the app from port 3000 to 3001 breaks the site until someone edits this line.
Test from the server itself. Run curl against the upstream address directly. If curl works and the site does not, the fault is inside Nginx. If curl fails, the fault is the app.
For PHP-FPM, check the socket file exists and that the Nginx user may read it. Permission denied on a socket looks identical to a dead service from outside.
- curl -i http://127.0.0.1:3000/ from the server
- ss -ltnp to list listening ports
- ls -l on the socket file
- nginx -t before every reload
When it works, then fails under load
Intermittent 502s usually come from limits. Worker processes in PHP-FPM run out, a Node process runs out of memory or a database pool fills up and requests stall until the app gives up.
Large response headers cause a quieter version. A framework that sets several big cookies can exceed proxy_buffer_size, and Nginx drops the response. Raise the buffers modestly rather than to huge values.
Compare timestamps. Be patient. Match the error log entries against the application log and the traffic spike. The pattern usually names the cause.
502 versus 504, and what to do next
A 502 says the upstream answered badly or not at all. A 504 says the upstream took too long and Nginx stopped waiting. The first points to crashes and addresses. The second does not. The second points to slow queries, long reports and proxy_read_timeout.
Do not raise timeouts as a first reaction. It hides the cause. A report that needs ten minutes belongs in a background job with a progress screen.
Keep a short runbook with the log path, the service name and the five commands above, so the next incident takes minutes.
- Log path and service names
- Last deploy time
- Upstream address in the config
- Memory use at the time of failure
502 triage card
A card of one page showing a numbered path: read the error log, match the reason, check the service, curl the upstream, compare the config. Beside each step is a blank for the finding and a column for the fix applied. A footer lists the log path, service name, config file and the person to call.
Open a blank worksheet to printQuestions owners ask
What is the difference between a 502 and a 504?
A 502 means the upstream returned an invalid response or none. A 504 means the upstream did not answer within the timeout. Crashes cause the first, slow work the second.
Why does the 502 appear only sometimes?
Usually the app restarts, runs out of workers or memory, or sends oversized headers under certain requests. Compare log timestamps with traffic and with process restarts.
Will restarting Nginx fix a 502?
Rarely. Nginx is normally healthy. Restart or repair the application it forwards to, and run nginx -t before any reload.
Should I increase proxy_read_timeout?
Only for a 504 and only after checking why the request is slow. Long work is better moved to a background job.
