PHP-FPM et Laravel : calcul du bon nombre de workers, gestion mémoire et alerting
PHP-FPM est le chef d'orchestre silencieux entre Nginx et votre application Laravel. Chaque requête HTTP devient un worker PHP-FPM qui bootstrap le framework, traverse les middlewares, appelle le contrôleur et retourne une réponse. La configuration par défaut est conçue pour ne rien casser — pas pour performer. Voici comment la calibrer concrètement.
Mesurer la mémoire réelle d'un worker
Avant de toucher le moindre paramètre, mesurez ce que consomme réellement un worker sur votre application. Les chiffres génériques ne servent à rien.
# Mémoire moyenne par process PHP-FPM actif
ps --no-headers -o rss -C php-fpm | awk '{sum+=$1} END {print sum/NR/1024 " MB"}'
Pour une vue plus précise en tenant compte de la mémoire partagée :
# Détail par PID (shared vs private)
for pid in $(pgrep php-fpm); do
awk '/^Pss:/{pss+=$2} END {print pss/1024 " MB"}' /proc/$pid/smaps
done
Sur une application Laravel standard (pas de bundles lourds), vous obtiendrez généralement entre 30 et 80 Mo par worker. Avec Octane ou des dépendances volumineuses, cela peut dépasser 120 Mo. Notez ce chiffre — il est la base de tous vos calculs.
La formule pour pm.max_children
Une fois la consommation moyenne connue, le calcul est direct :
pm.max_children = (RAM disponible pour PHP-FPM) / (mémoire moyenne par worker)
Exemple concret sur un serveur avec 4 Go de RAM :
- RAM système + Nginx + MariaDB ≈ 1 Go réservé
- RAM disponible pour PHP-FPM : 3 Go (3072 Mo)
- Mémoire par worker mesurée : 60 Mo
pm.max_children = 3072 / 60 ≈ **51**
Partez sur 48 pour garder une marge de sécurité. Ne surprovisionnez pas : des workers en excès saturent la RAM, déclenchent du swap et dégradent tout le serveur.
; /etc/php/8.3/fpm/pool.d/www.conf
pm.max_children = 48
pm.start_servers = 12
pm.min_spare_servers = 8
pm.max_spare_servers = 20
pm.max_requests = 500
pm.max_requests = 500 force le recyclage des workers après 500 requêtes, ce qui évite les fuites mémoire progressives — fréquentes sur des applications complexes.
Choisir le bon mode pm : static, dynamic ou ondemand ?
PHP-FPM propose trois stratégies de gestion des process. Le choix a un impact direct sur la stabilité et les coûts.
pm = static
Tous les workers sont créés au démarrage et restent en vie. Idéal pour un trafic élevé et constant. Prévisible, pas de latence de démarrage.
pm = static
pm.max_children = 48
➜ À privilégier sur un serveur dédié à Laravel avec charge soutenue.
pm = dynamic
PHP-FPM démarre avec start_servers workers et en crée à la demande jusqu'à max_children. Les workers inactifs sont détruits progressivement. Bon compromis pour une charge variable.
pm = dynamic
pm.max_children = 48
pm.start_servers = 12
pm.min_spare_servers = 8
pm.max_spare_servers = 20
➜ Mode recommandé pour la majorité des projets Laravel en production.
pm = ondemand
Les workers ne sont créés qu'à la réception d'une requête et sont détruits après un délai d'inactivité. Économise de la RAM mais introduit une latence à froid.
pm = ondemand
pm.max_children = 48
pm.process_idle_timeout = 10s
➜ Réservé aux environnements à faible trafic (staging, apps internes) où la RAM est précieuse.
Alerting : surveiller ce qui compte vraiment
Configurer PHP-FPM sans mettre en place d'alerting, c'est conduire sans tableau de bord. Voici les métriques critiques à surveiller.
Activer le status PHP-FPM :
; pool.d/www.conf
pm.status_path = /fpm-status
# Dans la config Nginx (accès local uniquement)
location /fpm-status {
allow 127.0.0.1;
deny all;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Interroger le status en CLI :
curl -s http://127.0.0.1/fpm-status?full | grep -E 'active processes|max active|listen queue'
Les 3 indicateurs à surveiller :
| Métrique | Seuil d'alerte | Signification |
|---|---|---|
listen queue |
> 0 de façon persistante | File d'attente saturée, ajouter des workers |
max active processes |
proche de max_children |
Risque de saturation imminente |
max children reached |
valeur croissante | Plafond atteint régulièrement |
Avec Prometheus + php-fpm_exporter, ces métriques s'intègrent directement dans Grafana. Sinon, un simple script cron qui parse /fpm-status et envoie une alerte Slack ou email suffit pour commencer.
# Alerte basique si listen queue > 0
LQ=$(curl -s http://127.0.0.1/fpm-status | grep 'listen queue:' | awk '{print $3}')
if [ "$LQ" -gt 0 ]; then
echo "⚠️ PHP-FPM listen queue = $LQ" | mail -s "Alerte FPM" admin@mulertech.net
fi
Conclusion
Tuner PHP-FPM n'est pas une opération complexe, mais elle demande de partir de données mesurées, pas de valeurs copiées-collées. La démarche est simple : mesurez la mémoire réelle d'un worker, calculez pm.max_children avec la formule, choisissez le mode pm adapté à votre profil de trafic, et mettez en place un alerting minimal sur la listen queue.
Sur un projet Laravel en production, ces ajustements peuvent doubler le débit ou réduire de moitié les temps de réponse sous charge — sans changer une ligne de code applicatif.
📎 Article inspiré de Tuning PHP-FPM for Laravel: Workers, Memory, and Process Management publié sur dev.to par Deploynix.