Independent comparison · no paid rankings
Home / Blog / Saturated PHP-FPM: tell too few workers from blocking code
Technical

Saturated PHP-FPM: tell too few workers from blocking code

PHP-FPM queue full? Before raising pm.max_children, check if workers sleep on an external API call or a 30-second SQL query.

4 min read Updated Jul 19, 2026

Nginx shows upstream timed out while reading response header from upstream. PHP-FPM reports listen queue len 32. Immediate reflex: raise pm.max_children from 50 to 150. Traffic absorbed—RAM hits 98%, OOM killer hits MySQL. Untreated cause: sync payment webhook 25 s per checkout.

Saturated PHP-FPM shows two diseases with similar symptoms: truly too few workers for short CPU load, or blocked workers on network I/O, slow SQL, file locks. Confusing the two costs RAM dearly—and hides the real bottleneck for weeks.

If slowlog shows the same stack trace everywhere, it is not an FPM problem—it is that stack trace.

Golden rule: 24 h slowlog, then pm tuning—never reverse. Raising max_children without shortening the critical path is hiring cashiers while every customer still pays with bad checks.

Read php-fpm status and slowlog

Enable visibility first:


pm.status_path = /fpm-status

ping.path = /fpm-ping

request_slowlog_timeout = 5s

slowlog = /var/log/php-fpm/slow.log

Protect /fpm-status behind nginx—do not expose publicly. Saturation signals:

  • active processes ≈ max constantly;
  • listen queue > 0;
  • logs server reached pm.max_children.

RAM formula: (max_children × memory per child) + OS + MySQL < total RAM—20% margin minimum.

Diagnosis A vs B: insufficient workers or blocking code

A — insufficient workers: requests under 200 ms, high PHP CPU, empty or diverse slowlog → raise pm.max_children in steps of ten, watching RAM.

B — blocking code: active workers, low CPU, slowlog concentrated on same line (curl, PDO, file_get_contents) → async queue, 3–5 s curl timeout, fix SQL index—see missing MySQL index and PHP profiling.

Align nginx fastcgi_read_timeout with app reality—a shorter nginx timeout than the webhook masks the problem as 504 without slowlog. On shared hosting, process cap imposed by host is an VPS upgrade signal rather than infinite tuning.

For N+1 queries, see dynamic site MySQL—a query loop can block all workers without high CPU.

pm tuning: dynamic, ondemand, static

ModeWhen to useRisk
dynamicVariable traffic, controlled RAMUnexpected peaks if max_children too low
ondemandSporadic traffic, limited RAMCold-start latency
staticFlat load, predictable RAMWaste if traffic trough

Start with pm = dynamic and pm.max_children from RAM formula. Try ondemand only if cold-start latency is acceptable for your audience.

The climax — more workers with blocking code

Compare VPS where you control PHP-FPM via the directory. On shared hosting, process cap is non-negotiable—diagnosis stays the same, but solution goes through upgrade or code optimization.

Decide and move forward without blind spots

Before raising max_children:

  1. Enable status and slowlog—without visibility, you tune blind.
  2. Classify saturation: high CPU (A) or busy workers low CPU (B).
  3. Fix code or SQL if slowlog is concentrated—no pm tuning before fix.
  4. Adjust pm.max_children in steps of ten with documented RAM budget.
  5. Align nginx fastcgi_read_timeout and app timeouts (curl, PDO).
  6. Load-test same endpoint after fix—queue should stay zero under normal load.

Frequently asked questions

How do you know PHP-FPM is saturated?

listen queue above zero, max_children reached logs, nginx 502/504, linear latency with traffic. Enable pm.status_path to observe before outage—not only after.

Is raising max_children enough?

Temporarily for diagnosis A. Calculate available RAM; if slowlog is concentrated, fix code first—doubling workers with blocking code causes OOM kill.

How to spot blocking code?

PHP-FPM slowlog and profiling tool. Symptom: all workers busy, low CPU. Same trace everywhere = identified bottleneck—not too few workers.

ondemand vs dynamic?

dynamic or ondemand for variable traffic; static for flat load. ondemand saves RAM but adds startup latency—test in staging.


Saturated PHP-FPM means too few registers—or motionless cashiers. Confusing the two costs RAM dearly.

Compare European hosts

Filter by compliance, location and use case — then open the sheets to verify the real scope.

Browse the directory
Blog

Related reading

All articles →