Tutti gli articoliPerformance

PHP-FPM sizing: come dimensionare davvero i worker su WordPress

PHP-FPM lento o instabile non si aggiusta alzando numeri a caso. Devi misurare RAM per processo, coda richieste e comportamento del traffico.

7 aprile 2026·10 min lettura·Aggiornato il 7 aprile 2026
Scheda editoriale
Scritto da
Team Operations SysExperts
Redazione tecnica infrastruttura
Revisione tecnica
Revisione interna SysExperts
DBA & Performance Engineer
Stack testato
PHP 8.2PHP-FPMWordPressNginxDebian 12
PHP-FPM sizing: come dimensionare davvero i worker su WordPress

Molti siti WordPress lenti non hanno un problema di codice. Hanno un pool PHP-FPM dimensionato male. Troppi pochi worker e le richieste si accodano. Troppi worker e il server finisce RAM, swap o OOM killer.

Questa guida ti spiega come dimensionare PHP-FPM in modo misurabile, senza formule da forum e senza copiare configurazioni di altri.

Se il sintomo iniziale è TTFB alto generalizzato, affianca questa lettura a Sito lento: 5 cause server-side e come risolverle. Se devi intervenire su un server già in crisi, puoi partire da SOS o dal servizio Performance Tuning.

TL;DR

Il sizing corretto di PHP-FPM si basa su questa sequenza:

  1. misura quanta RAM usa davvero un processo PHP
  2. definisci quanta RAM totale puoi assegnare a PHP
  3. calcola pm.max_children
  4. osserva coda, saturazione e swap
  5. ritocca solo dopo aver visto i dati

Il punto non è avere più worker possibile. Il punto è avere abbastanza worker da gestire il traffico, senza uccidere il resto del server.

Step 1: capisci che macchina stai gestendo

Prima domanda: quel server fa solo PHP o fa anche altro?

Esempi:

  • web + db sullo stesso server
  • web separato da db
  • web + Redis + cron + queue workers
  • hosting multi-sito con decine di pool

Se il server è condiviso, PHP non può mangiarsi tutta la RAM.

free -h
ps aux --sort=-%mem | head -20

Devi stimare la memoria riservata a:

  • sistema operativo
  • Nginx o Apache
  • MySQL o MariaDB
  • Redis, cron, agent monitoring
  • margine di sicurezza

Step 2: misura la RAM per processo PHP

Questa è la metrica più importante.

ps -ylC php-fpm --sort:rss

Oppure, se vuoi una media semplice:

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

Come leggere il numero

Se il processo medio usa:

  • 50 MB: WordPress abbastanza leggero
  • 80-120 MB: stack normale con plugin e admin traffic
  • 150 MB o più: plugin pesanti, WooCommerce, page builder, import o query brutte

Non usare il valore del processo più piccolo. Usa una media realistica o, meglio, il percentile alto durante carico normale.

Step 3: calcola la RAM assegnabile a PHP

Esempio pratico su server da 8 GB:

  • 1.5 GB OS + servizi base
  • 2 GB MySQL
  • 0.5 GB Redis, monitoring, margine
  • restano circa 4 GB per PHP

Se un processo medio PHP usa 80 MB:

4096 / 80 = 51

Quindi pm.max_children intorno a 45-50 ha senso.

Se ogni processo usa 140 MB:

4096 / 140 = 29

In quel caso impostare pm.max_children = 60 è una ricetta per l'OOM killer.

Step 4: controlla che ci sia davvero coda

Molti alzano pm.max_children senza sapere se PHP è veramente saturo.

Abilita lo status page del pool.

pm.status_path = /status
ping.path = /ping

Poi esponila solo in locale o dietro restrizioni e interroga:

curl -s http://127.0.0.1/status?full

Metriche chiave:

  • listen queue
  • max children reached
  • idle processes
  • active processes

Interpretazione pratica

  • listen queue > 0 in modo ricorrente: richieste in attesa
  • max children reached > 0: il pool sta saturando
  • molti idle processes costanti: pool sovradimensionato

Step 5: scegli la modalità corretta

pm = dynamic

È quasi sempre la scelta giusta per WordPress.

pm = dynamic
pm.max_children = 45
pm.start_servers = 8
pm.min_spare_servers = 6
pm.max_spare_servers = 12
pm.max_requests = 500

pm = ondemand

Utile su server con tanti siti a basso traffico, dove vuoi risparmiare RAM quando non arriva traffico.

pm = static

Ha senso solo in casi particolari, con carico molto prevedibile e tuning rigoroso.

Configurazione di partenza sensata

Per un WordPress medio su Nginx con 4 GB dedicabili a PHP:

pm = dynamic
pm.max_children = 40
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm.max_requests = 500
request_terminate_timeout = 120s

Non è una verità universale. È un punto di partenza da validare.

pm.max_requests: il parametro che molti ignorano

Serve a riciclare i processi dopo un certo numero di richieste.

Perché è utile:

  • limita memory leak applicativi
  • evita processi gonfiati da plugin o script lunghi
  • stabilizza il comportamento nel tempo

Valori tipici:

  • 300
  • 500
  • 1000

Se hai plugin o estensioni poco pulite, meglio stare più bassi.

Segnali di sizing sbagliato

Troppo basso

  • TTFB alto a picchi
  • listen queue non zero
  • utenti admin che si lamentano di lentezza intermittente
  • max children reached nei log o status

Troppo alto

  • swap che sale
  • MySQL che soffre improvvisamente
  • OOM killer in dmesg
  • tutto il server rallenta sotto carico
dmesg | grep -i "killed process"
vmstat 1 5

Errore classico: contare solo il frontend

Molti misurano il sito pubblico e ignorano:

  • wp-admin
  • wp-cron
  • WooCommerce checkout
  • import/export
  • plugin backup
  • scansioni o indexer

Il sizing va fatto sul traffico reale, non sulla home page in cache.

Quando il problema non è PHP-FPM

Non toccare PHP-FPM se il collo di bottiglia è altrove:

  • database lento
  • disco saturo o I/O scarso
  • cache applicativa assente
  • query esterne lente
  • DNS o API terze parti

Per questo conviene incrociare i dati con MySQL buffer pool tuning: guida basata sui dati e con Monitoring, observability e NOC 24/7.

Procedura pratica di tuning

1. fotografia iniziale

free -h
ps --no-headers -o rss -C php-fpm | awk '{sum+=$1; n++} END {print sum/n/1024 " MB"}'
curl -s http://127.0.0.1/status?full

2. prima ipotesi

Calcoli RAM disponibile e pm.max_children.

3. modifica controllata

systemctl reload php8.2-fpm

4. osservazione

Per almeno 24-72 ore:

  • RAM
  • swap
  • queue
  • TTFB
  • errori applicativi

5. secondo ritocco

Piccolo. Non raddoppiare i numeri a caso.

Quando questa guida non basta

Questa guida basta per pool PHP-FPM relativamente lineari. Non basta se:

  • hai molti pool per molti clienti sullo stesso nodo
  • usi container o orchestrazione con limiti rigidi
  • il traffico è fortemente bursty
  • c'è WooCommerce pesante con checkout concorrenti
  • il database è già il collo di bottiglia

In questi casi ti serve una lettura trasversale di CPU, RAM, database, cache e traffico. Parti da audit gratuito o dal servizio Performance Tuning.

Checklist finale

  • misurata RAM per processo
  • stimata RAM disponibile a PHP
  • calcolato pm.max_children
  • abilitato status page
  • controllati listen queue e max children reached
  • verificato swap e OOM
  • eseguito tuning incrementale

PHP-FPM non è un parametro da indovinare. È una capacità operativa da dimensionare. Quando lo tratti così, i siti smettono di essere “misteriosamente lenti”.

Prossimo passo

Pronto a smettere di occuparti dei server?

Audit scritto, zero impegni, report PDF con assessment della tua situazione.