The FPM master (root, under systemd 142,543 ) reads /etc/php/8.5/fpm/pool.d/*.conf and forks workers for each pool. Give each site a pool with its own user, socket and limits, and point its virtual host at the socket (PHP-FPM via proxy_fcgi):
[shop]
user = shop
listen = /run/php/shop.sock
listen.owner = www-data
pm = dynamic
pm.max_children = 8
pm.min_spare_servers = 1
pm.max_spare_servers = 3pm.start_servers defaults to the mean of the spare limits, 2 here. Worker counts with pm.max_children = 8, idle, under 16 concurrent 50 ms requests, and 1 and 13 seconds after the load stopped:
| pm | Idle | Load | +1 s | +13 s |
|---|---|---|---|---|
| static | 8 | 8 | 8 | 8 |
| dynamic (spare 1-3) | 2 | 5 | 6 | 3 |
| ondemand (idle 10 s) | 0 | 8 | 8 | 5 |
static keeps every worker: the steadiest latency on a dedicated server. dynamic, Ubuntu 225 's default (with five children), holds idle workers between the spare limits and forks one, then two, then four per second, so it had only 5 after three seconds. ondemand forks on arrival and kills workers idle for pm.process_idle_timeout: right for many small sites on one box.