Error fix · Developer errors

PHP-FPM Server Reached pm.max_children: Size Your Pool Correctly

Fix the PHP-FPM warning server reached pm.max_children by measuring worker memory, setting pm.max_children from real RAM, and finding slow requests.

Error messageWARNING: [pool www] server reached pm.max_children setting (5), consider raising it

By SiteDownCheck Editorial · Updated November 11, 2026 · 4 min read

The PHP-FPM log line server reached pm.max_children setting (N), consider raising it means every worker process in the pool was busy when another request arrived. PHP-FPM cannot start more workers than pm.max_children, so new requests wait in the listen queue. Visitors experience slow pages, then timeouts, 502 or 504 errors from the web server in front.

WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

The advice "consider raising it" is only half the story. Raising the limit helps if you have spare memory and the workers are busy doing legitimate work. If requests are slow because of a hung database, an external API, or a lock, more workers just move the pile-up around and can exhaust RAM, which is worse. So measure before you change.

Step 1: how much memory does a worker use?

ps --no-headers -o rss -C php-fpm8.2 | awk '{sum+=$1; n++} END {printf "workers=%d avg=%.0f MB\n", n, sum/n/1024}'
free -m

Use the process name for your version (php-fpm, php-fpm8.2, php8.2-fpm). Resident memory overstates real use a little because workers share code pages, but it is a safe planning number. WordPress with several plugins often uses 50 to 150 MB per worker, and a WooCommerce or heavy admin request can use more.

Step 2: calculate a safe maximum

Take the memory you can give PHP and divide by the average (or a high percentile) worker size:

pm.max_children ~= (total RAM - RAM for OS, database, nginx, cache) / average worker size

Example: a 4 GB VPS with 1.5 GB reserved for MariaDB, the OS, and nginx leaves 2.5 GB. At 80 MB per worker, that supports about 30 workers. Leave a margin; if the machine starts swapping, response times collapse. Check OOM kills if workers disappear under load.

Step 3: set the pool values

Edit the pool file (for example /etc/php/8.2/fpm/pool.d/www.conf):

pm = dynamic
pm.max_children = 30
pm.start_servers = 8
pm.min_spare_servers = 4
pm.max_spare_servers = 12
pm.max_requests = 500
pm.status_path = /fpm-status
  • dynamic scales between the spare limits. It suits most sites.
  • ondemand starts workers only when needed and kills idle ones. It saves memory on many small pools, with a startup cost per burst.
  • static keeps a fixed count. It is predictable on dedicated machines with steady load.
  • pm.max_requests recycles a worker after N requests, limiting the damage from memory leaks in extensions.

Test and reload:

sudo php-fpm8.2 -t
sudo systemctl reload php8.2-fpm

Also set listen.backlog if the queue overflows; check the kernel's net.core.somaxconn limit too.

Step 4: find out why workers are busy

If you raise the limit and the warning returns, something holds workers too long. Enable the slow log:

request_slowlog_timeout = 5s
slowlog = /var/log/php8.2-fpm.slow.log

The slow log prints a PHP backtrace for any request exceeding five seconds, which usually points to a slow query, a remote API call without a timeout, or a lock. Also expose the status page and check the active and queue counters (curl http://127.0.0.1/fpm-status, restricted to localhost in your nginx config).

Common root causes:

  • Slow database queries or a saturated database. Read MySQL too many connections and lock wait timeout.
  • External APIs and payment gateways with no timeout. Set cURL and stream timeouts.
  • Bots and crawlers hammering uncached pages. Add caching, rate limits or a WAF rule.
  • Uncached WordPress pages or admin-ajax abuse. See WordPress slow site checklist and WordPress WP-Cron explained.
  • Long-running exports and imports inside web requests. Move them to queue workers or cron.
  • Session locks where one request holds the session file open and blocks others for the same user.

Step 5: match nginx timeouts

When the pool is full, nginx waits for a worker and may give up, producing 504 Gateway Timeout or nginx upstream timed out. See nginx 502 and 504 timeout tuning. A restart of PHP-FPM can also produce brief 502s; see fix 502 Bad Gateway.

Verify and monitor

After changes, watch the log for the warning, and test with real traffic or a modest load test. Measure server response with the Website Speed Test and the Website Health Check, and see the broader picture in the Site Health Report. Alert on slowness with an Uptime Monitor; response-time trends often rise before the warning appears. Check regional reachability with Down From Where if timeouts are intermittent.

Next steps

FAQ

What value should pm.max_children have?

Available RAM for PHP divided by average worker memory, with a safety margin. There is no universal number.

Which pm mode is best?

Dynamic is a good default, ondemand saves memory on idle pools, and static suits steady dedicated workloads.

Will adding RAM fix it?

Only if workers are limited by memory. If requests are slow because of a database or API, fix that first.

Does the warning mean the site is down?

Not by itself, but it means requests are queuing, and visitors may see slowness or errors.

Get notified when this fix updates

Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.

This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.