keepcalculator

06 Numbers and Powers

Fix Nginx PHP-FPM Upstream Timed Out Errors

Card No. 06·30125 · Updated · Standard formula, shown below

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.conf or /etc/php-fpm.d/www.conf)
  • A text editor (nano, vim, or similar)
  • Ability to reload Nginx and PHP-FPM services

Step-by-Step

  1. Identify the exact error. Check your Nginx error log (commonly /var/log/nginx/error.log) for lines containing upstream timed out. Note the upstream address (e.g., unix:/run/php/php8.1-fpm.sock or 127.0.0.1:9000) – you’ll need it later.
  2. Open your Nginx site configuration. Locate the server block that handles the domain or path causing the timeout. Edit the file with sudo nano /etc/nginx/sites-available/your-site.
  3. Add or adjust the proxy_read_timeout directive. Inside the location block that passes requests to PHP-FPM (usually location ~ \.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).
  4. Set fastcgi_read_timeout if you use FastCGI. For PHP-FPM, Nginx uses the fastcgi module. Add fastcgi_read_timeout 300; inside the same location block. This is the most direct fix for PHP-FPM timeouts.
  5. Increase proxy_connect_timeout and proxy_send_timeout. Add proxy_connect_timeout 75; and proxy_send_timeout 300; to the same location block. These handle connection establishment and sending data to PHP-FPM.
  6. Check the PHP-FPM pool configuration. Open the pool file (e.g., sudo nano /etc/php/8.1/fpm/pool.d/www.conf). Look for request_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 check max_execution_time in 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.
  7. Test your Nginx configuration. Run sudo nginx -t to verify there are no syntax errors. If successful, you’ll see “syntax is ok” and “test is successful”.
  8. Reload Nginx and PHP-FPM. Apply changes with sudo systemctl reload nginx and sudo systemctl reload php8.1-fpm (adjust version). Reloading is safer than restarting because it doesn’t drop connections.
  9. 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 location that handles PHP, not the server block. 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_timeout and max_execution_time.
  • Using proxy_read_timeout instead of fastcgi_read_timeout. For PHP-FPM, the relevant directive is fastcgi_read_timeout. The proxy_* 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 -T to dump the effective configuration and search for fastcgi_read_timeout. Confirm it’s set in the right location.
  • Check if the script itself is hanging. Use strace or 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_timeout in the upstream context 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

The whole Numbers and Powers drawer →