Why My Laravel Production App Is Crashing at 8 PM: Solving PHP‑FPM Timeouts on cPanel Shared Hosting with Docker‑Lite
It’s 8 PM. Your monitoring dashboard flashes red, users can’t submit forms, and the error log is exploding with FastCGI: comm with server “unix:/opt/php-fpm.sock” aborted: timeout. You’re on a shared cPanel box, you’ve just added a Docker‑Lite environment for a queue worker, and the whole Laravel site collapses like a house of cards. Sound familiar? You’re not alone.
Why This Matters
Every lost request after hours means lost revenue, a bruised brand, and a frantic on‑call rotation. In the SaaS world, a single timeout can trigger a cascade: failed API calls, dead queue jobs, and a sudden spike in CPU that forces your host to throttle or even suspend the account. Understanding the root cause—and fixing it—keeps your Laravel app smooth, your WordPress integration fast, and your customers happy.
Common Causes of 8 PM Crashes
- PHP‑FPM
max_childrenhit during traffic spike. - Docker‑Lite container starving for CPU/memory on shared hosting.
- Long‑running queue workers that never exit, exhausting FPM slots.
- Mis‑configured Nginx/Apache fastcgi buffers.
- MySQL lock contention caused by heavy reporting queries.
- Redis cache miss flood when the TTL expires at the top of the hour.
- Composer autoloader bloat after a recent
composer update.
Step‑By‑Step Fix Tutorial
1. Diagnose the Timeout
First, confirm the error source.
tail -f /home/username/logs/php-fpm/error.log | grep "timeout"
Look for lines that mention request_terminate_timeout or pm.max_children.
2. Increase PHP‑FPM Limits
Edit the PHP‑FPM pool file (usually /opt/php73/etc/php-fpm.d/www.conf on cPanel).
[www]
pm = dynamic
pm.max_children = 30 ; raise from default 12
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
request_terminate_timeout = 120 ; seconds
After saving, restart PHP‑FPM:
/usr/local/bin/php-fpm -y /opt/php73/etc/php-fpm.conf --reload
pm.max_requests to 500 to force graceful worker recycling and avoid memory leaks.3. Optimize Docker‑Lite Resource Limits
Add a docker-compose.yml snippet that caps CPU and memory:
services:
queue-worker:
image: yourrepo/laravel-queue
deploy:
resources:
limits:
cpus: '0.75'
memory: 512M
restart: unless-stopped
Deploy the changes:
docker compose up -d --no-deps --force-recreate queue-worker
4. Tune Nginx FastCGI Buffers (or Apache Proxy)
If you’re using Nginx as a reverse proxy, add these directives to your site block:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/opt/php73/var/run/www.sock;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_read_timeout 90;
}
For Apache with mod_proxy_fcgi:
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/home/username/public_html/$1
5. Offload Heavy Queries to Redis
Cache the hourly report data that kills MySQL.
// In a Laravel service provider
Cache::remember('hourly_report', 55, function () {
return DB::table('orders')
->selectRaw('SUM(total) as total, DATE(created_at) as day')
->where('created_at', '>=', now()->subHour())
->groupBy('day')
->get();
});
6. Restart Supervisor Workers
Ensure Supervisor respects the new PHP‑FPM limits.
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/public_html/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
numprocs=3
user=username
stopwaitsecs=360
stdout_logfile=/home/username/logs/queue.log
stderr_logfile=/home/username/logs/queue-error.log
Reload Supervisor:
supervisorctl reread && supervisorctl update && supervisorctl restart laravel-queue:*
numprocs higher than your PHP‑FPM max_children or you’ll create a deadlock.VPS or Shared Hosting Optimization Tips
- Use OPcache. Add
opcache.enable=1andopcache.memory_consumption=192tophp.ini. - Limit Composer autoload. Run
composer dump-autoload -oafter each deploy. - Swap wisely. On VPS, enable a 1 GB swap file to avoid OOM kills.
- Separate Redis. If possible, use a managed Redis instance to free local RAM.
- Enable HTTP/2. Both Nginx and Apache support it; it reduces latency for API calls.
Real World Production Example
Company Acme SaaS ran a Laravel API on a 2 CPU cPanel shared plan. Their nightly email campaign triggered a queue:work container at 20:00. After applying the steps above they saw:
| Metric | Before | After |
|---|---|---|
| CPU Avg | 85 % | 42 % |
| PHP‑FPM Timeouts | 12/hr | 0 |
| Redis Cache Misses | 8,320 | 1,210 |
Before vs After Results
# BEFORE
[20:00] PHP-FPM: request timeout (max 30s)
[20:00] Docker container OOM killed
[20:01] 502 Bad Gateway errors spike
# AFTER
[20:00] PHP-FPM: all workers healthy
[20:00] Docker container uses 0.6 CPU / 400M RAM
[20:01] 0 error responses, API latency 120ms
Security Considerations
- Never expose Docker socket directly to the web; bind it to localhost.
- Use
--read-onlyflag for containers that only need to read the codebase. - Restrict
php.inidisable_functionsto blockexec,shell_execif not needed. - Enable
mod_securityon Apache orngx_http_limit_req_moduleon Nginx to mitigate brute‑force API calls.
Bonus Performance Tips
- Enable Laravel route cache:
php artisan route:cache. - Cache config:
php artisan config:cache. - Use
php artisan view:cachefor Blade templates. - Set
SESSION_DRIVER=redisandCACHE_DRIVER=redisin.env. - Compress assets with
laravel-mix --productionand serve via Cloudflare CDN.
FAQ
Q: I’m on a cPanel host that doesn’t let me edit
php-fpm.conf. What can I do?A: Use a custom
.user.inito setrequest_terminate_timeoutandmax_execution_time. Also, push the heavy job to a separate Docker container that runs under its own user.
Q: My queue jobs still hang after the fix.
A: Add
--timeout=120to thequeue:workcommand and ensure Supervisor’sstopwaitsecsis higher than that value.
Final Thoughts
Time‑outs at 8 PM are rarely a mystical bug; they’re a symptom of resource contention, mis‑configured FPM pools, and unchecked container consumption. By tightening PHP‑FPM, sandboxing Docker‑Lite, and leveraging Redis and OPcache, you can keep a Laravel app stable on even the most modest shared host. The same principles apply when you later migrate to a VPS or a dedicated cloud instance—just scale the numbers.
If you’re looking for an affordable, secure hosting platform that plays nicely with cPanel, Docker‑Lite, and Laravel, check out Hostinger’s cheap secure hosting. Their burstable CPU and built‑in Redis add‑on make the transition painless.
No comments:
Post a Comment