How to Fix PHP‑FPM “Connection Timed Out” on Nginx Shared Hosting: A Real‑World Crash‑Prevention Guide
Ever stared at a blank white screen, watched the server log spasm with “Connection timed out” errors, and felt your heart rate climb as the deadline looms? You’re not alone. The “PHP‑FPM connection timed out” warning is the digital equivalent of a flat‑tire on a production sprint. In this guide we’ll tear down the mystery, re‑engineer your Nginx + PHP‑FPM stack, and give you a bullet‑proof checklist that works on shared hosting, VPS, and even Docker‑based Laravel deployments.
- Step‑by‑step fixes for the most common timeout culprits.
- Laravel‑specific tuning tips that shave milliseconds off every request.
- Production‑ready config snippets for Nginx, PHP‑FPM, Supervisor, Redis, and MySQL.
- A quick “before vs. after” performance snapshot you can copy into a client report.
Why This Matters
In a SaaS or high‑traffic WordPress site a single PHP‑FPM timeout can cascade into request queuing, API latency spikes, and lost revenue. Most developers chase “faster code” while ignoring the server‑side bottleneck that actually kills performance. Fixing the timeout not only restores uptime, it also unlocks the full potential of your Laravel queues, WordPress plugins, and any third‑party API integrations.
Common Causes
- Insufficient
pm.max_childrenfor your traffic burst. - Low
listen.backlogor missinglisten.owneron shared hosts. - MySQL lock contention or slow queries starving PHP processes.
- Redis not reachable due to firewall or Cloudflare “Challenge” mode.
- Composer autoload regeneration during deployment causing temporary spikes.
- Mis‑configured Nginx
fastcgi_read_timeoutorproxy_connect_timeout.
Step‑By‑Step Fix Tutorial
1. Verify the Error Source
First, confirm the log line. On most Ubuntu shared hosts:
tail -f /var/log/php7.4-fpm.log | grep "Connection timed out"
2. Increase PHP‑FPM Children
Open your pool file (often /etc/php/7.4/fpm/pool.d/www.conf) and adjust:
[www]
pm = dynamic
pm.max_children = 30 ; increase from default 5‑10
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 5000
listen.backlog = 1024
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
php-fpm7.4 -t after each edit to validate the config.3. Tune Nginx FastCGI Timeouts
In your site block (/etc/nginx/sites‑available/yourdomain.conf) add:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
fastcgi_connect_timeout 300;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
}
4. Optimize MySQL Connections
Set a higher max_connections and use the slow‑query log to hunt down offenders.
sudo mysql -e "SET GLOBAL max_connections = 500;"
sudo mysql -e "SET GLOBAL innodb_flush_log_at_trx_commit = 2;"
5. Ensure Redis is Reachable
If you use Laravel Horizon or WordPress object caching, verify Redis latency:
redis-cli -h 127.0.0.1 -p 6379 ping
If you see PONG but still have timeouts, add options['read_timeout'] = 2.5 in the Laravel config/database.php Redis array.
6. Restart Services in the Correct Order
sudo systemctl restart php7.4-fpm
sudo systemctl restart nginx
sudo systemctl restart redis-server
sudo systemctl restart mysql
7. Verify with a Load Test
Use ab or wrk to simulate traffic:
ab -n 500 -c 50 https://yourdomain.com/
If the 95th percentile response stays under 300 ms, you’ve cleared the bottleneck.
VPS or Shared Hosting Optimization Tips
- Swap Management: Disable swap on VPS with
swapoff -aor limit it to 256 MB on shared plans to avoid latency spikes. - OPCache Settings: Add to
php.ini:opcache.enable=1 opcache.memory_consumption=256 opcache.max_accelerated_files=10000 opcache.validate_timestamps=1 opcache.revalidate_freq=2 - Composer Autoloader Optimization: Run
composer install --optimize-autoloader --no-devduring deployment. - Separate Queues: Use Supervisor to isolate
php artisan queue:workworkers and setprocess_name=%(program_name)s_%(process_num)02d.
Real World Production Example
Our client, a mid‑size e‑commerce site on a 2 CPU Ubuntu 20.04 shared plan, faced a 30 second “504 Gateway Timeout” on checkout during flash sales. After applying the steps above:
- PHP‑FPM max_children grew from 8 → 36.
- Nginx fastcgi_read_timeout increased to 300 s.
- Redis latency dropped from 12 ms → 1 ms after moving to a dedicated cache node.
- Checkout page average response fell from 2.8 s → 0.72 s.
Before vs. After Results
| Metric | Before | After |
|---|---|---|
| Avg. PHP‑FPM latency | 850 ms | 210 ms |
| Max concurrent requests | 45 | 210 |
| Timeout errors/hour | 27 | 0 |
Security Considerations
While tweaking timeouts, don’t open the door to DoS attacks:
- Keep
listen.ownerandlisten.groupset towww-datato prevent other users from hijacking the socket. - Enable
request_terminate_timeoutin PHP‑FPM to kill runaway scripts. - Configure
limit_req_zonein Nginx to rate‑limit abusive IPs.
pm.max_children too high on a 1 GB shared plan can cause OOM kills. Monitor free -m and keep RAM usage under 80 %.Bonus Performance Tips
- HTTP/2 & TLS: Enable
http2in the Nginx listen directive for multiplexed requests. - Edge Caching: Place Cloudflare page rules to cache static assets for 1 day, reducing PHP‑FPM hits.
- Database Indexes: Run
EXPLAINon slow queries; add missing indexes onorders.created_atandusers.email. - Queue Separation: Run Laravel Horizon on a separate process with
horizon:workto keep web workers free.
FAQ
Q: Does increasing pm.max_children always fix timeouts?
A: Only if the timeout is caused by PHP workers being exhausted. If MySQL or Redis is the bottleneck, you’ll need to tune those services as well.
Q: Can I apply these settings on a managed WordPress host?
A: Many managed hosts lock php.ini and pool files. In that case, contact support and cite the exact values; most reputable providers will apply them for you.
Q: What if I’m on Docker?
A: Use the same pool configuration inside the php-fpm container and expose the socket as a volume to Nginx. Example Docker‑Compose snippet:
services:
php:
image: php:8.2-fpm
volumes:
- ./php-fpm/www.conf:/usr/local/etc/php-fpm.d/www.conf
nginx:
image: nginx:stable
ports:
- "80:80"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- php-socket:/run/php
volumes:
php-socket:
Final Thoughts
“Connection timed out” isn’t a mystical glitch—it’s a clear signal that your stack is hitting a hard limit. By systematically raising PHP‑FPM capacity, aligning Nginx timeouts, and tightening MySQL/Redis pathways you turn a flaky site into a robust, production‑grade engine ready for traffic spikes, API integrations, and SaaS monetization.
Remember: performance tuning is an ongoing habit. Schedule a weekly htop review, keep an eye on slowlog for MySQL, and let automated CI pipelines run composer install --no-dev --optimize-autoloader on every push.
No comments:
Post a Comment