Bug corrigé en production — ticket clos. Les utilisateurs voient encore l'erreur. Cache CDN ? Vidé. Opcode ? opcache.validate_timestamps=0 depuis un réglage « performance » : les fichiers PHP sont bien mis à jour sur disque, mais l'ancien bytecode reste servi quarante minutes jusqu'au redémarrage paniqué de PHP-FPM.
OPcache est une accélération — mal géré en production, c'est un cache de code qui ignore vos déploiements. L'enjeu n'est pas « vider le cache » ; c'est synchroniser la release sur le disque et les workers PHP sans provoquer une cascade de 502.
Cycle de déploiement sain
Un déploiement PHP fiable suit une séquence documentée :
- Release atomique :
/releases/20260719/plus symlinkcurrent. - Composer install, migrations, préchauffage du cache applicatif.
php artisan optimizeou cache Symfony si applicable.- Rechargement PHP-FPM :
systemctl reload php8.2-fpm(gracieux). - Test de fumée sur le point de contrôle de santé.
- Retour arrière = revert du symlink plus rechargement.
Le reload recycle les workers progressivement — les requêtes en cours se terminent ; les nouveaux workers chargent un OPcache frais. Un restart brutal provoque une coupure ; le reload est le choix préféré pour un déploiement sans interruption.
restart brutal versus reload gracieux : le premier interrompt le service ; le second préserve les connexions en cours.
validate_timestamps : le compromis à comprendre
| Réglage | Comportement | Usage |
|---|---|---|
validate_timestamps=1 | stat() sur le fichier, recompile si mtime change | Développement, préproduction |
validate_timestamps=0 | ne revérifie jamais le disque | Production plus rechargement à chaque déploiement |
Avec revalidate_freq=0 et validate=1, chaque requête vérifie le disque — une charge d'entrées-sorties inutile en production. Le couple validate_timestamps=0 plus rechargement FPM scripté est le standard des équipes qui déploient plusieurs fois par semaine.
Stratégies d'invalidation
A — Rechargement FPM (recommandé) Étape post-déploiement dans le script : systemctl reload php-fpm. Simple, prévisible, sans interruption majeure.
B — opcache_reset() en ligne de commande post-déploiement Via SSH en one-shot — acceptable si un seul pool PHP-FPM. Jamais dans une requête HTTP.
C — Déploiement progressif sur N serveurs Répartiteur de charge en drain → déploiement → rechargement → réactivation. Zéro interruption sur un cluster.
D — opcache.file_cache Second niveau sur disque — attention à la synchronisation entre nœuds lors du déploiement.
Pièges multi-version et conteneurs
- Blue-green avec deux releases : workers mixtes si rechargement partiel — terminez le rechargement sur tous les nœuds avant de basculer le trafic.
- Preloading PHP 7.4+ : un changement de fichier preload exige un redémarrage complet, pas un simple reload.
- Docker : nouvelle image = nouveau conteneur, OPcache frais. Montage de volume pour le code = même problème de
validate_timestamps.
Sur un hébergement mutualisé, pas de rechargement FPM en self-service — déploiement FTP avec validate_timestamps=1 imposé ou ticket support. Raison de plus pour un VPS ou un PaaS si vous déployez fréquemment.
Le sommet : OPcache sans procédure de déploiement, c'est du test A/B involontaire
Voici ce que les réglages « performance » oublient de documenter.
Checklist déploiement PHP : symlink plus rechargement FPM documenté — pas « on upload et on espère ».
Décider et avancer sans angle mort
Sur une demi-journée, vous pouvez sécuriser vos déploiements PHP :
- Passez
validate_timestamps=0en production avec rechargement FPM scripté. - Mettez en place un déploiement atomique par symlink.
- Rendez obligatoire un test de fumée post-rechargement.
- Interdisez
opcache_reset()dans les endpoints web. - Planifiez un déploiement progressif si vous avez plusieurs serveurs.
Documentez la séquence complète dans votre runbook de déploiement : qui lance le rechargement, comment vérifier que tous les workers ont recyclé, et quel test confirme que le nouveau code est bien servi. Croisez avec Profiling PHP pour mesurer l'impact d'un mauvais déploiement, et Déploiement blue-green pour les architectures à plusieurs instances.
Questions fréquentes
Pourquoi l'ancien code tourne après deploy ?
OPcache conserve le bytecode compilé en mémoire. Avec validate_timestamps=0, les fichiers modifiés sur disque ne déclenchent aucun rechargement tant qu'un worker n'est pas recyclé via un rechargement FPM.
opcache_reset() en prod est-il sûr ?
Non en requête web — c'est un reset global brutal. Préférez un rechargement gracieux de PHP-FPM ou un reset en ligne de commande post-déploiement, hors trafic utilisateur.
validate_timestamps=1 en production ?
Possible en préproduction. En production, cela ajoute des appels stat() à chaque inclusion. Le compromis courant reste validate_timestamps=0 plus rechargement FPM à chaque déploiement.
Le déploiement atomique aide-t-il ?
Oui. La bascule de symlink plus le rechargement FPM synchronisent tous les workers sur la même arborescence de fichiers, sans mélange d'anciennes et nouvelles releases.
Après un déploiement, si OPcache n'a pas été invité à la fête, vous maintenez deux versions du site — une dans git, une en RAM.