Guide

PHP-FPM: perché ‘pm static’ batte ‘dynamic’ e ‘ondemand’ sui server ad alto traffico

Dario Fadda Luglio 9, 2026

Il problema: PHP-FPM e l’overhead della gestione dei processi

Chi gestisce server PHP ad alto traffico (WordPress incluso, come questo stesso blog) conosce bene il dilemma: come configurare il process manager di PHP-FPM per ottenere throughput elevato, latenza bassa e un uso stabile di CPU e memoria? La configurazione di default nella maggior parte delle installazioni è pm = dynamic, con il consiglio ricorrente di passare a ondemand quando la memoria disponibile scarseggia. Ma su server che ricevono traffico costante, entrambe le opzioni introducono un overhead di gestione dei processi che una configurazione static ben dimensionata elimina quasi del tutto.

I tre modelli di process manager

PHP-FPM offre tre strategie per gestire i processi figli (worker), definite dalla direttiva pm in php-fpm.conf:

  • pm = dynamic — il numero di processi figli varia dinamicamente in base a pm.max_children, pm.start_servers, pm.min_spare_servers e pm.max_spare_servers.
  • pm = ondemand — i processi vengono creati solo quando arriva una richiesta, invece di essere avviati insieme al servizio come accade con dynamic.
  • pm = static — il numero di processi figli è fisso, determinato unicamente da pm.max_children.

La lista completa delle direttive è documentata nel file php-fpm.conf di riferimento su php.net.

Un’analogia utile: il governor della CPU

Il trade-off tra questi modelli ricorda da vicino quello dei governor CPUFreq su Linux: ondemand scala la frequenza in base al carico corrente, salendo subito al massimo e riducendo gradualmente nei periodi di inattività; conservative fa lo stesso ma in modo più graduale; performance mantiene sempre la CPU alla frequenza massima. Impostare PHP-FPM su static equivale concettualmente a impostare il governor su performance: si rinuncia al risparmio di risorse in idle in cambio di una risposta immediata, senza il tempo di “spin-up” necessario a creare nuovi worker.

Quando e come usare pm static

La bontà di pm static dipende interamente dalla memoria disponibile sul server. Se la RAM è limitata, ondemand o dynamic restano scelte più sicure. Se invece la memoria c’è, conviene eliminare l’overhead del process manager impostando pm.max_children al massimo che il server può sostenere senza saturare memoria o CPU.

La regola pratica: non indovinare il valore di pm.max_children, ma misurarlo. Prima si calcola la dimensione media (RSS) di un worker PHP-FPM sotto carico reale:

ps --no-headers -o rss -C php-fpm | awk '{ sum += $1; n++ } END { print sum/n/1024 " MB" }'

Poi si divide la memoria che si intende dedicare a PHP-FPM per questo valore medio. Se un worker occupa in media 60 MB e si vogliono destinare 6 GB a PHP-FPM, il calcolo è 6144 / 60 ≈ pm.max_children = 100. È fondamentale lasciare margine per sistema operativo, web server e database, evitando di assegnare a PHP-FPM tutta la RAM fisica disponibile.

Una configurazione tipica su un server con 32 GB di RAM potrebbe essere:

pm = static
pm.max_children = 100
pm.max_requests = 1000

Con questi valori, anche con circa 200 utenti attivi simultanei (dato realistico osservato con Google Analytics), circa il 70% dei worker resta inattivo ma pronto: non deve essere creato al volo quando arriva un picco di traffico, e non viene distrutto dopo il timeout di pm.process_idle_timeout come accadrebbe con dynamic. Il valore di pm.max_requests va tenuto alto (o a 0, se non si hanno memory leak noti negli script) proprio per evitare che il process manager ricicli continuamente i worker, vanificando il vantaggio di static.

Per verificare lo stato dei processi in tempo reale è sufficiente:

top -bn1 | grep php-fpm

Quando invece conviene ondemand o dynamic

Con pm = dynamic capita spesso di incontrare un warning simile a questo:

WARNING: [pool xxxx] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 4 idle, and 59 total children

Il consiglio classico è aumentare i valori minimi, ma su traffico molto variabile il tuning di dynamic resta complesso. Passare a ondemand aiuta a risparmiare memoria, ma su un server costantemente sotto carico introduce l’effetto opposto: i worker vengono azzerati appena il traffico cala, per poi dover essere ricreati non appena il traffico torna, spostando il costo dalla memoria alla latenza di avvio.

dynamic e soprattutto ondemand restano invece la scelta giusta in scenari multi-tenant, ad esempio server con decine o centinaia di pool PHP-FPM distinti (hosting condiviso, molteplici account cPanel). In questi casi, dove la maggior parte dei siti riceve poco o nessun traffico, ondemand spegne i worker inattivi risparmiando enormi quantità di memoria complessiva — motivo per cui cPanel lo ha reso il default al posto di dynamic.

Conclusione

Su un server che serve traffico consistente, dynamic e ondemand aggiungono un overhead di gestione dei processi che una configurazione static correttamente dimensionata elimina. La chiave non è scegliere una configurazione “alla cieca”, ma misurare il consumo reale di memoria dei worker, calcolare pm.max_children di conseguenza, lasciare margine per il resto dello stack e poi validare sotto carico reale (ad esempio con benchmark ab) osservando CPU, memoria e tempi di risposta. Con pm static, poiché i worker restano residenti in memoria, i picchi di traffico si traducono in variazioni di carico molto più contenute, con tempi di risposta più stabili nel tempo.

Fonte originale: LinuxBlog.io – PHP-FPM tuning: Using ‘pm static’ for max performance

💬 Unisciti alla discussione!


Questo è un blog del Fediverso: puoi trovare quindi questo articolo ovunque con @blog@spcnet.it e ogni commento/risposta apparirà qui sotto.

Se vuoi commentare su PHP-FPM: perché ‘pm static’ batte ‘dynamic’ e ‘ondemand’ sui server ad alto traffico, utilizza la discussione sul Forum.
Condividi la tua esperienza, confrontati con altri professionisti e approfondisci i dettagli tecnici nel nostro 👉 forum community