PHP preloading (PHP 7.4+) — preload.php and opcache.preload
Advanced5 min read·php-15-009
performance
Concept
PHP-FPM (FastCGI Process Manager) manages a pool of PHP worker processes that serve web requests. Its configuration directly impacts application performance and capacity.
How PHP-FPM works: A web server (Nginx/Apache) receives HTTP requests and passes them to PHP-FPM via FastCGI. PHP-FPM maintains a pool of worker processes. Each worker handles one request at a time, then returns to the pool. The number of workers determines concurrency — more workers means more simultaneous requests, but also more memory.
Process management modes (pm directive):
static: Fixed number of workers (pm.max_children). Workers are always running. Best for high-traffic servers where you want predictable memory usage and no spawn overhead.dynamic: Workers spawn and die based on demand. Bounded bypm.min_spare_servers,pm.max_spare_servers,pm.max_children. Good for variable traffic.ondemand: Workers start on demand and stop when idle forpm.process_idle_timeout. Best for low-traffic servers (saves memory when idle).
Key tuning knobs:
pm.max_children: Maximum number of workers.floor(available_memory / memory_per_worker). Measure a worker's memory withps aux | grep php-fpm | awk '{print $6}'(RSS in KB). Typical Laravel worker: 50-100MB.pm.max_requests: Workers restart after this many requests (prevents memory leaks from accumulating). 500-1000 is typical.request_terminate_timeout: Kill stuck workers after N seconds.listen.backlog: Queue of pending connections waiting for an available worker.
Code Example
ini
; /etc/php/8.2/fpm/pool.d/www.conf
[www]
; Socket (faster than TCP) or TCP
listen = /run/php/php8.2-fpm.sock
; listen = 127.0.0.1:9000
; Worker count: floor(available_RAM / avg_worker_RAM)
; 4GB server, 100MB per worker: floor(3500 / 100) = 35 workers
pm = dynamic
pm.max_children = 35
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500 ; restart worker after 500 requests (memory leak prevention)
; Slow request logging
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s ; log requests taking more than 5 seconds
; Kill stuck requests
request_terminate_timeout = 60s
; Process title in ps output
process.user = www-data
process.group = www-data
; Environment variables for the pool
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[APP_ENV] = productionbash
# Check current PHP-FPM processes and memory usage
ps aux | grep php-fpm | awk '{sum+=$6} END {print "Total: " sum/1024 " MB"}'
# Reload config without downtime
systemctl reload php8.2-fpm
# Monitor status endpoint (enable in pool config: pm.status_path = /fpm-status)
curl http://127.0.0.1/fpm-status
# Shows: active, idle, max active, accepted connections, etc.