When Nginx returns a 504 Gateway Timeout or logs “upstream timed out” while talking to PHP-FPM, it means a request took longer than Nginx was configured to wait. This guide walks through the exact configuration changes to extend timeouts, tune PHP-FPM, and test the fix without breaking your site.
What You’ll Need
- Root or sudo access to your server (SSH)
- Your Nginx site configuration file (usually in
/etc/nginx/sites-available/or/etc/nginx/conf.d/) - The PHP-FPM pool configuration file (often
/etc/php/8.x/fpm/pool.d/www.confor/etc/php-fpm.d/www.conf) - A text editor (nano, vim, or similar)
- Ability to reload Nginx and PHP-FPM services
Step-by-Step
- Identify the exact error. Check your Nginx error log (commonly
/var/log/nginx/error.log) for lines containingupstream timed out. Note the upstream address (e.g.,unix:/run/php/php8.1-fpm.sockor127.0.0.1:9000) – you’ll need it later. - Open your Nginx site configuration. Locate the
serverblock that handles the domain or path causing the timeout. Edit the file withsudo nano /etc/nginx/sites-available/your-site. - Add or adjust the
proxy_read_timeoutdirective. Inside thelocationblock that passes requests to PHP-FPM (usuallylocation ~ \.php$), add or change:proxy_read_timeout 300;. This tells Nginx to wait up to 300 seconds for a response from PHP-FPM. Adjust the number based on your needs (60 for short requests, 600 for long-running scripts). - Set
fastcgi_read_timeoutif you use FastCGI. For PHP-FPM, Nginx uses thefastcgimodule. Addfastcgi_read_timeout 300;inside the same location block. This is the most direct fix for PHP-FPM timeouts. - Increase
proxy_connect_timeoutandproxy_send_timeout. Addproxy_connect_timeout 75;andproxy_send_timeout 300;to the same location block. These handle connection establishment and sending data to PHP-FPM. - Check the PHP-FPM pool configuration. Open the pool file (e.g.,
sudo nano /etc/php/8.1/fpm/pool.d/www.conf). Look forrequest_terminate_timeout. If it’s set (e.g.,request_terminate_timeout = 60), increase it to match your Nginx timeout, or comment it out to disable. Also checkmax_execution_timein your PHP ini (usually/etc/php/8.1/fpm/php.ini) – set it to a value slightly higher than your Nginx timeout, e.g.,max_execution_time = 300. - Test your Nginx configuration. Run
sudo nginx -tto verify there are no syntax errors. If successful, you’ll see “syntax is ok” and “test is successful”. - Reload Nginx and PHP-FPM. Apply changes with
sudo systemctl reload nginxandsudo systemctl reload php8.1-fpm(adjust version). Reloading is safer than restarting because it doesn’t drop connections. - Test the fix. Trigger the slow script again. If it completes within the new timeout, the error is gone. If not, check the logs again – you may need to increase the values further or address the root cause (e.g., a slow database query).
Common Mistakes
- Setting timeouts in the wrong location block. The directives must be inside the
locationthat handles PHP, not theserverblock. If you put them at the server level, they may not apply to the PHP location. - Forgetting to match PHP-FPM’s timeout. Even if Nginx waits 300 seconds, PHP-FPM may kill the script after 60 seconds. Always check
request_terminate_timeoutandmax_execution_time. - Using
proxy_read_timeoutinstead offastcgi_read_timeout. For PHP-FPM, the relevant directive isfastcgi_read_timeout. Theproxy_*directives apply to HTTP proxying (like to a Node.js app). - Not testing after reload. Sometimes the reload fails silently or you forget to reload PHP-FPM. Always test with a real request.
- Setting timeouts to extremely high values. This can mask underlying performance issues and tie up server resources. Use the smallest value that works.
Tips
- Use
fastcgi_connect_timeout(default 60s) to control how long Nginx waits to connect to PHP-FPM. If PHP-FPM is overloaded, this can be the culprit. - If you use a Unix socket for PHP-FPM (e.g.,
unix:/run/php/php8.1-fpm.sock), the connect timeout is usually not an issue, but the read timeout still applies. - For long-running tasks (like report generation), consider moving them to a background queue (e.g., using a message queue) instead of increasing timeouts indefinitely.
- Monitor your PHP-FPM status page (if enabled) to see if workers are busy or idle. Overloaded workers can cause timeouts even with generous timeouts.
- Keep a backup of your configuration before editing, so you can revert quickly.
Troubleshooting
If the timeout persists after making changes:
- Check the error log again. The error may have changed. If you see “connect() failed” or “Connection refused”, PHP-FPM might be down or the socket path is wrong. Verify PHP-FPM is running with
sudo systemctl status php8.1-fpm. - Verify that your changes actually took effect. Run
nginx -Tto dump the effective configuration and search forfastcgi_read_timeout. Confirm it’s set in the right location. - Check if the script itself is hanging. Use
straceor check PHP-FPM’s slow log (if enabled) to see where the script is stuck. The timeout may be a symptom of a deadlock or an infinite loop. - Test with a simple PHP script. Create a file that sleeps for 10 seconds and see if it times out. If it doesn’t, the issue is specific to your application.
- Look for other timeouts in the chain. If you use a reverse proxy in front (like Cloudflare), it may have its own timeout (e.g., 100 seconds). You can’t change that, so you may need to optimize the script or use a different approach.
- If you’re using a load balancer or upstream block, check the
proxy_read_timeoutin theupstreamcontext as well – it can override location settings.
Frequently Asked Questions
What is the default fastcgi_read_timeout in Nginx?
The default is 60 seconds. If your PHP script takes longer than that, you’ll get a 504 error unless you increase it.
Should I set fastcgi_read_timeout to 0 to disable it?
Setting it to 0 is not recommended. It means Nginx will wait indefinitely, which can tie up resources and make the server unresponsive. Use a reasonable value like 300 or 600 seconds.
What’s the difference between fastcgi_read_timeout and proxy_read_timeout?
fastcgi_read_timeout is specifically for FastCGI upstreams (like PHP-FPM). proxy_read_timeout is for HTTP proxying. For PHP-FPM, you need the fastcgi directive.
Why does my PHP script still time out even after increasing Nginx timeouts?
Check PHP-FPM’s request_terminate_timeout and PHP’s max_execution_time. If either is lower than your Nginx timeout, the script will be killed before Nginx gives up.
Can I set timeouts per location?
Yes, you can set different timeouts in different location blocks. For example, a location for a file upload endpoint can have a longer timeout than the rest of the site.
Will increasing timeouts affect performance?
It can. If many requests hang for a long time, PHP-FPM workers will be occupied, reducing capacity for other requests. Only increase timeouts as needed and try to fix the underlying slow code.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Connect Phone to Controller for Cloud Gaming
- Python Search Highlighting: Snippets & Matches
- Secure Boot Battlefield 6 ASUS: Fix & Enable Guide
- Best Tech Websites to Follow for Pros & Beginners
- Second Wind Quest Walkthrough: Where Winds Meet6.00 min/km
- Enshrouded Weapon Upgrade Guide: How to Improve Gear5.00 min/km