504 Gateway Timeout Under Load: Fix Nginx PHP-FPM
A 504 under load means your app can't respond fast enough. Usually it's PHP-FPM or Nginx timeout settings. I'll show you the real fix.
Quick Answer
Raise fastcgi_read_timeout in Nginx and max_execution_time in PHP-FPM. Also check PHP-FPM's pm.max_children setting. That's the short version.
Context
You get a 504 Gateway Timeout when your web app runs a script that takes too long to finish. Under load, this happens because PHP-FPM processes get busy, and the server gives up waiting. I've seen this with WordPress on a shared host that suddenly gets 1000 visitors, or a custom API that processes big files. The error appears in Nginx as upstream timed out (110: Connection timed out) in logs. It's frustrating because the app seems fine on low traffic.
Most guides tell you to increase a bunch of timeouts. But the real issue is often PHP-FPM running out of workers, or a script that slows down under load. Let's fix both.
Step-by-Step Fix
- Check Nginx logs – Look at
/var/log/nginx/error.log. Search for504orupstream timed out. This tells you if it's PHP-FPM or a proxy.sudo tail -100 /var/log/nginx/error.log | grep -i '504\|timeout' - Increase Nginx timeout for PHP – Edit your Nginx server block (usually
/etc/nginx/sites-available/your-site). Add or change this in thelocation ~ \.php$block:
Then test and reload Nginx:fastcgi_read_timeout 300s;sudo nginx -t && sudo systemctl reload nginx - Raise PHP max execution time – Edit
/etc/php/8.2/fpm/php.ini(adjust version to yours). Findmax_execution_timeand set to 300:
If you use a config override likemax_execution_time = 300/etc/php/8.2/fpm/pool.d/www.conf, add it there:php_admin_value[max_execution_time] = 300 - Increase PHP-FPM workers – In the pool config (same
www.conf), adjust these:
Save, restart PHP-FPM:pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20sudo systemctl restart php8.2-fpm - Also check Nginx proxy timeouts – If your app uses Nginx as a reverse proxy for Node.js or another service, add these in the
location /block:proxy_read_timeout 300s;
proxy_connect_timeout 75s;
Alternative Fixes
If the 504 still appears after the steps above, try these:
- Switch to static process manager – Change
pm = dynamictopm = staticand setpm.max_childrento a fixed number based on your server RAM (e.g., 50 for a 4GB server). This prevents PHP-FPM from crashing under load spikes. - Enable slow log – Add to
www.conf:request_slowlog_timeout = 10sandslowlog = /var/log/php-slow.log. Then watch that log to find which scripts are slow. Kill them or optimize. - Use a CDN or cache plugin – For WordPress, install a cache plugin like W3 Total Cache and a CDN like Cloudflare. This reduces PHP requests a lot.
- Upgrade PHP version – PHP 8.2 is faster than 7.4. If you're on old PHP, upgrade. I've seen 504s disappear after moving from 7.4 to 8.2.
Prevention Tip
Monitor your server resources. Set up a cron job that checks PHP-FPM process count and alerts you if it hits 80% of max_children. Also set pm.max_requests = 500 in your pool config to avoid memory leaks. And test your app with a load testing tool like ab (Apache Bench) or wrk before going live. A 504 under load is a symptom of a bottleneck. Fix the bottleneck, not just the timeout.
Was this solution helpful?