The site won't come up and the browser just shows a number: 502 Bad Gateway. If Nginx is standing in front of the request, this message means Nginx sent the request to the backend and didn't get a response from it. So the problem is almost always on the backend side, not in Nginx and not in the user's browser. The first thing you should do is figure out which layer didn't respond.
Where the 502 error comes from
An HTTP request from the browser to PHP has several stops. Each stop can produce a 502, and each one has its own log:
- Browser → Cloudflare (or any CDN): if the edge can't connect to the origin, it returns a 502.
- Cloudflare → Nginx: if the origin's port 80/443 is closed, the same 502.
- Nginx → PHP-FPM: if the FPM socket or port doesn't respond, Nginx returns a 502 error.
- PHP-FPM → MySQL or Redis: here you usually get a 500, but if the FPM worker dies, the result is a 502.
The troubleshooting order is from the outside in. First see whether the error is coming from Cloudflare or from the server itself.
Quick diagnosis: is the error from the CDN or the server
Send a direct request to the server IP and look at the headers:
curl -sSI -H "Host: example.com" http://185.x.x.x/ | head -n 5
If the direct response was 200 but the domain behind Cloudflare gives a 502, the problem is at the edge or in the origin settings. If both give a 502, go to the Nginx log:
tail -f /var/log/nginx/error.log
The line you're looking for is something like this:
connect() to unix:/run/php/php8.2-fpm.sock failed (11: Resource temporarily unavailable)
Or:
upstream prematurely closed connection while reading response header from upstream
The first means the FPM worker queue is full. The second means PHP died mid-execution. These two have completely different treatments.
PHP-FPM timeout and full worker queue
PHP-FPM has a limited number of workers. When all workers are busy, a new request stays in the queue, and if Nginx gives up before FPM does, it returns a 502. You need to look at two numbers side by side: request_terminate_timeout in FPM and fastcgi_read_timeout in Nginx.
If fastcgi_read_timeout is set to 60 seconds and a script takes 90 seconds, Nginx closes the connection at second 60 and the user sees a 502, while PHP is still working and keeping the worker occupied. This is where people make a mistake: they set fastcgi_read_timeout to infinity to make the error go away. The error goes away, but the queue stays full and ten minutes later the whole site gives a 502. The sign is also that the site is fine for a few minutes and then suddenly all requests hang.
The right way is to first figure out which script is taking long. Enable the FPM slow log:
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
After a few minutes, the slow.log file tells you exactly which function and which line of code is taking time. In nine out of ten cases, it's a query without an index or an HTTP request to an external API.
Correctly setting pm.max_children
Calculate the number of workers based on memory, not guesswork. If each PHP process takes about 80 megabytes of RSS and the server has 4 gigabytes of RAM, the logical ceiling is around 30 to 35 workers, not 100. Simple formula:
pm = dynamic
pm.max_children = 32
pm.start_servers = 8
pm.min_spare_servers = 8
pm.max_spare_servers = 16
pm.max_requests = 500
Don't underestimate pm.max_requests. Memory leaks in WordPress plugins are real, and periodic worker restarts prevent many gradual 502s.
The role of Cloudflare in the 502 error
Cloudflare returns a 502 when it can't connect to the origin or the origin doesn't give a valid response. Three common causes:
- The origin IP has changed in the DNS record and the old A record remains. Use the DNS and network lookup tool to check that the A and AAAA records point to the correct IP.
- The server firewall has blocked Cloudflare's IPs. If you have iptables or CSF, Cloudflare's ranges must be allowed.
- The SSL mode is set to
Full (strict)but the certificate on the origin has expired. Here the browser sees a 502 and the origin log has nothing.
A point that misleads many people: Cloudflare doesn't cache the origin error, but it returns its own error page with the 502 code. If you see cf-ray in the browser's Network tab, it means the error came from the edge and you should check the origin log separately.
When workers are exhausted but the server is healthy
There's a case where CPU and RAM are completely free, but the site gives a 502. This almost always means FPM workers are stuck waiting on an external resource: a locked MySQL connection, a Redis that isn't responding, or a curl request without a timeout to an external service.
To see the current queue status:
systemctl status php8.2-fpm
ss -x -p | grep php
If the number of socket connections is unusually high and isn't decreasing, a script is putting all the workers to sleep. In this situation, increasing pm.max_children only postpones the pain. You need to find the script.
In WordPress, wp-cron.php is one of the usual suspects on high-traffic sites. Every visit creates a separate cron request and on high traffic it fills the worker queue. The standard solution is to disable the internal cron and run it with the system crontab:
define('DISABLE_WP_CRON', true);
*/5 * * * * wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
When the problem is server resources
If after correctly configuring FPM and finding the slow script, you still get 502s during peak hours, it's no longer a configuration issue; the server has hit its ceiling. Here you have two options and the choice between them depends on the load pattern.
| Situation | Logical choice |
|---|---|
| Steady traffic, stable memory usage, only CPU rises at peak | Upgrading the Linux hosting plan |
| Need for precise kernel tuning, service isolation, or irregular and heavy load | Dedicated or virtual server with full control |
If you control the code and configuration yourself and want to freely tune FPM and cache parameters, Linux hosting with full SSH access is the better choice than staying and fighting 502s every week. If your site's load is constant and heavy and you need to isolate the database from the web server, a dedicated server is more logical.
Five-minute checklist
- Look at
/var/log/nginx/error.logand grab the exact upstream message. - Check the service health with
systemctl status php8.2-fpm. - Compare the
pm.max_childrenvalue with the server's actual memory. - Enable the FPM slow log and find the culprit script.
- If you're behind Cloudflare, check the DNS record and SSL mode.
If after these five steps you still have the error, it's time to look at the architecture, not the configuration. The guide on diagnosing a slow website is a good starting point, because 502s and slowness usually share the same root. For cases related to web server-level configuration, ServerNet's documentation and knowledge base has ready-made examples.
Frequently asked questions
What's the difference between a 502 and a 504 error?
502 means the backend gave an invalid response or the connection was cut; 504 means the backend gave no response within the specified period. In practice, 504 is usually solved by increasing the timeout, but 502 is a sign of worker failure or saturation. If you see both, first check the PHP-FPM worker queue.
Does restarting PHP-FPM fix the 502 error?
Temporarily yes, but it doesn't fix the cause. If after systemctl restart php8.2-fpm the site is fine for a few hours and then gives a 502 again, it means a script or memory leak is killing the workers. Enable the FPM slow log to see the culprit.
Why do only some users get the 502 error?
Because the error depends on a specific worker. If one of several backend servers is broken, or one node in the load balancer is out of service, only part of the requests reach it. Also, if the edge cache serves part of the pages, other users don't reach the origin at all and don't see the error.
Does the 502 error affect SEO?
Yes, and its effect is quick. If Google's crawler sees a 502 on several consecutive visits, the site's crawl rate drops and pages get indexed later. If the error lasts more than a few hours, there's a chance pages are temporarily removed from the results. Prioritize getting the site back up, then move on to optimization.
Comments 0
No comments yet — be the first!