Sur un site WordPress à fort trafic, la configuration PHP-FPM par défaut de la plupart des hébergements est presque toujours sous-dimensionnée ou mal adaptée au profil réel de charge. Le symptôme classique : des pages qui répondent normalement en heures creuses, puis des erreurs 502 ou des temps de réponse qui explosent dès qu’un pic de trafic survient, sans que le CPU ou la RAM du serveur ne semblent pourtant saturés.
Le problème vient presque toujours du pool PHP-FPM : trop peu de processus disponibles pour absorber les requêtes simultanées, ou à l’inverse une configuration qui gaspille la mémoire en gardant des processus inactifs. Voici comment régler finement pm, calculer pm.max_children et surveiller le tout avec la page de statut intégrée.
Rappel du fonctionnement d’un pool PHP-FPM
PHP-FPM (FastCGI Process Manager) gère un ensemble de processus PHP appelés workers, organisés en pools. Chaque requête PHP reçue par le serveur web (Nginx ou Apache) est transmise à un worker disponible du pool, qui l’exécute puis se libère pour la requête suivante. Si toutes les workers sont occupés au moment d’une nouvelle requête, celle-ci attend en file, avec un risque de timeout si l’attente dépasse le délai configuré.
La directive pm du fichier de configuration du pool (généralement /etc/php/8.1/fpm/pool.d/www.conf ou équivalent selon la version de PHP) détermine comment ces workers sont gérés.
pm static, dynamic ou ondemand : trois logiques différentes
Le choix de la valeur de pm a un impact direct sur la consommation mémoire et la latence de réponse.
| Mode | Comportement | Cas d’usage recommandé |
|---|---|---|
| static | Nombre fixe de workers, tous démarrés dès le lancement de PHP-FPM | Trafic élevé et stable, RAM disponible garantie |
| dynamic | Nombre de workers variant entre un minimum et un maximum, ajusté selon la charge | Trafic variable avec pics prévisibles |
| ondemand | Workers créés à la demande et tués après une période d’inactivité | Trafic faible ou irrégulier, mutualisation de ressources |
Pour un WordPress à fort trafic, static est souvent le meilleur choix : en fixant un nombre de processus constant, on élimine la latence de démarrage d’un nouveau worker au moment d’un pic, latence qui peut se faire sentir avec dynamic lorsque le nombre de workers actifs doit augmenter rapidement. La contrepartie est une consommation mémoire constante, même en heures creuses, ce qui suppose une RAM correctement dimensionnée.
[www]
user = www-data
group = www-data
listen = /run/php/php8.1-fpm-monsite.sock
pm = static
pm.max_children = 40
pm.max_requests = 500
Calculer pm.max_children selon la RAM disponible
C’est le calcul le plus important, et le plus souvent bâclé. pm.max_children définit le nombre maximal de processus PHP-FPM simultanés. Une valeur trop basse limite artificiellement la capacité du serveur à absorber du trafic concurrent ; une valeur trop haute risque de saturer la RAM disponible et de déclencher l’OOM killer du système, qui tuera des processus au hasard, PHP-FPM y compris.
La formule de base :
pm.max_children = (RAM disponible pour PHP-FPM en Mo) / (poids moyen d'un process PHP-FPM en Mo)
Pour mesurer le poids moyen réel d’un process, la commande suivante sur le serveur donne une estimation fiable une fois le site sous charge normale :
ps -ylC php-fpm8.1 --sort:rss | awk '{ sum += $8; count++ } END { print sum / count / 1024 " Mo en moyenne" }'

Sur un WordPress avec plusieurs plugins lourds (constructeur de pages, WooCommerce, cache), il n’est pas rare d’observer une moyenne autour de 25 à 40 Mo par process, contre 15 à 20 Mo pour une installation plus légère. Exemple de calcul pour un serveur disposant de 4 Go de RAM, dont on réserve 1 Go pour le système, MySQL et Nginx, laissant 3 Go pour PHP-FPM :
- RAM disponible pour PHP-FPM : environ 3 000 Mo.
- Poids moyen mesuré par process : 30 Mo.
pm.max_children= 3 000 / 30 = 100 processus maximum.
Avec pm = static, il faut aussi s’assurer que cette valeur ne dépasse jamais ce que la RAM peut réellement supporter en pic, sans marge de sécurité supplémentaire pour d’autres services sur la même machine.
Régler pm.start_servers, pm.min_spare_servers et pm.max_spare_servers
Ces trois directives ne s’appliquent qu’en mode dynamic :
pm.start_servers: nombre de processus lancés au démarrage de PHP-FPM.pm.min_spare_servers: nombre minimal de processus inactifs maintenus en réserve.pm.max_spare_servers: nombre maximal de processus inactifs tolérés avant que PHP-FPM n’en arrête certains.
Une bonne pratique consiste à fixer pm.start_servers à une valeur proche de la charge moyenne observée, plutôt qu’à une valeur minimale, pour éviter les montées en charge trop lentes lors des premières requêtes après un redémarrage.
[www]
pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500
Surveiller le pool avec la status page de PHP-FPM
PHP-FPM expose une page de statut intégrée qui donne une vision en temps réel de l’état du pool : nombre de processus actifs, inactifs, nombre de connexions en attente, nombre maximal de processus atteint depuis le dernier redémarrage. Il faut d’abord l’activer dans la configuration du pool :
[www]
pm.status_path = /status
Puis configurer Nginx pour exposer cette route de façon sécurisée, réservée aux IP de confiance :
location = /status {
allow 127.0.0.1;
deny all;
fastcgi_pass unix:/run/php/php8.1-fpm-monsite.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Conseil maison : surveillez en particulier le champ
max children reachedde la status page. Un compteur qui grimpe régulièrement signale quepm.max_childrenest trop bas pour le trafic réel, et que le serveur met des requêtes en attente derrière une file saturée, même si aucune erreur visible n’apparaît côté visiteur.
La status page peut être consultée au format texte simple ou en JSON, ce dernier étant plus pratique pour une intégration dans un outil de supervision externe :
curl "https://monsite.fr/status?json"
En résumé
Le tuning PHP-FPM ne se résume pas à augmenter des chiffres au hasard jusqu’à ce que les erreurs 502 disparaissent. Il repose sur trois piliers : choisir le bon mode pm selon le profil de trafic, calculer pm.max_children à partir d’une mesure réelle de la RAM consommée par process, et surveiller en continu la status page pour ajuster ces valeurs au fil de l’évolution du trafic. Sur un WordPress à fort trafic, ce réglage a souvent plus d’impact sur la stabilité en pic que n’importe quel plugin de cache.