PHP-FPM
debt(d5/e3/b7/t5)
Closest to 'specialist tool catches' (d5). The term's detection_hints.tools lists php-fpm-status, datadog, and prometheus — these are specialist monitoring/observability tools, not default linters or compilers. Misconfiguration (pm.max_children too low causing 502s, memory growth from no pm.max_requests) requires deliberate instrumentation to catch before production impact.
Closest to 'simple parameterised fix' (e3). The quick_fix shows a parameterised configuration change (pm=dynamic, pm.max_children formula, pm.max_requests=500) that can be applied in the php-fpm pool config file. It's not a one-liner (multiple parameters to tune based on server resources), but it's contained to configuration files without touching application code.
Closest to 'strong gravitational pull' (b7). PHP-FPM pool configuration is a load-bearing infrastructure choice that affects every PHP request in a web context. The applies_to shows it's fundamental to web PHP deployments. Misconfiguration shapes system behaviour under load — throughput, memory usage, and concurrency are all determined by these settings. Every scaling decision and performance investigation passes through this layer.
Closest to 'notable trap' (t5). The misconception explicitly states developers believe 'pool configuration is a set-and-forget server setting' when it actually requires tuning per application and server. This is a documented gotcha that experienced PHP developers eventually learn, but the default assumption that DevOps handles this and developers needn't care is common and leads to production issues.
Also Known As
TL;DR
Explanation
PHP-FPM (FastCGI Process Manager) runs PHP as a separate service communicating with the web server (typically Nginx) via FastCGI. It manages a pool of PHP worker processes, restarting crashed workers, and supports dynamic/static/ondemand process management strategies. Key configuration includes pm.max_children (limits concurrency and memory), request_terminate_timeout (prevents runaway processes), and slowlog (identifies slow scripts). Unlike Apache mod_php, PHP-FPM isolates PHP execution from the web server, improving security and allowing different pools per virtual host.
Diagram
flowchart TD
REQ[HTTP Request] --> NGINX[nginx]
NGINX -->|FastCGI| MASTER[PHP-FPM Master]
MASTER --> W1[Worker 1<br/>handling request]
MASTER --> W2[Worker 2<br/>idle]
MASTER --> W3[Worker 3<br/>idle]
W1 --> OPCACHE[OPcache<br/>compiled bytecode]
W1 --> DB[(Database)]
W1 --> REDIS[(Redis)]
INFO[Each worker handles one request<br/>pm.max_children = concurrency limit]
style MASTER fill:#6e40c9,color:#fff
style W1 fill:#238636,color:#fff
style OPCACHE fill:#1f6feb,color:#fff
style INFO fill:#d29922,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Using the default pm = dynamic settings without tuning for your application's memory per worker.
- Setting pm.max_children too high — workers exceed available RAM and the server starts swapping.
- Not setting request_terminate_timeout — runaway scripts hold workers indefinitely, starving new requests.
- Not monitoring the PHP-FPM slow log — slow requests are invisible without it.
Code Examples
# php-fpm pool.conf — untuned defaults:
pm = dynamic
pm.max_children = 50 ; Too high if each worker uses 100MB — that's 5GB RAM
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
; request_terminate_timeout = 0 — infinite by default, runaway scripts block workers
; /etc/php/8.3/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
pm = dynamic
pm.max_children = 50 ; workers x memory < available RAM
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 10
pm.max_requests = 500 ; recycle to prevent memory leaks
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
pm.status_path = /fpm-status
chdir = /var/www/app
php_admin_value[open_basedir] = /var/www/app:/tmp
php_admin_value[disable_functions] = exec,system,shell_exec