Le cache peut réduire les temps de réponse et la charge sur les bases de données ou les services externes, mais il ne corrige pas à lui seul une requête inefficace ni une architecture dont les limites sont mal définies. Une stratégie de cache en PHP doit préciser ce qui est stocké, qui peut le recevoir, combien de temps cela reste valide et ce qui se passe si le mécanisme de stockage tombe en panne.
La réussite ne se mesure pas uniquement à l’augmentation du taux de succès du cache. L’application doit respecter ses règles métier lorsque le cache est vide, obsolète ou indisponible. Pour y parvenir, il convient de commencer par mesurer le problème et de traiter le cache comme une optimisation au comportement vérifiable, et non comme la source de vérité principale.
Mesurer avant de décider quoi stocker

Commencez par identifier les routes lentes et leurs causes. Enregistrez les temps de réponse par endpoint, la latence des requêtes, les appels aux services externes, l’utilisation du processeur et le volume de requêtes. Distinguez les moyennes des percentiles élevés : une moyenne acceptable peut masquer des réponses très lentes pour une partie des utilisateurs.
Recherchez les opérations répétées dont le résultat change moins souvent que la demande : catalogues, configuration publique, contenu publié ou agrégats coûteux. Vérifiez également si la lenteur provient de requêtes sans index, d’un trop grand nombre de requêtes, de la sérialisation ou de tâches répétées au cours d’une même requête. Il peut être préférable d’optimiser la requête plutôt que de stocker un résultat difficile à invalider.
Définissez une référence avant le changement : performances, charge et qualité des données observée. Comparez ensuite le même trafic ou un test reproductible. S’il est impossible d’attribuer l’amélioration au cache, il sera difficile d’évaluer son coût opérationnel et ses effets secondaires.
Choisir entre le cache applicatif, HTTP et celui des requêtes
Le cache applicatif stocke des valeurs que le code PHP peut réutiliser, comme les résultats d’une requête ou une réponse calculée. Il peut résider dans une mémoire partagée, un service dédié ou un autre backend compatible avec l’application. Il convient lorsque plusieurs requêtes ont besoin du même résultat et que sa portée et sa durée de validité peuvent être définies avec précision.
Le cache HTTP utilise des directives comme Cache-Control, ETag et des validateurs, afin que les navigateurs ou les intermédiaires puissent réutiliser les réponses. Il est utile pour les ressources publiques ou les réponses dont la politique de confidentialité autorise le stockage. Les réponses personnalisées exigent une attention particulière : une politique publique peut exposer des données, tandis qu’une politique privée ou interdisant le stockage peut réduire cette possibilité, selon le flux et les intermédiaires impliqués.
Le cache des requêtes peut être une fonctionnalité de la base de données, du pilote ou d’une couche qui conserve les résultats. Il ne faut pas le confondre avec l’optimisation de l’accès aux données : le cache ne remplace ni les index, ni des plans de requête adaptés, ni les transactions. Avant de l’activer, comprenez qui invalide les entrées et si les lectures doivent refléter immédiatement les écritures.
Choisissez la couche la plus proche du problème, pas toutes les couches à la fois. Empiler des caches sans modèle explicite peut conduire différentes couches à conserver des versions différentes des mêmes données et compliquer le diagnostic.
Concevoir les clés, la portée et la durée d’expiration
Une clé doit identifier tous les facteurs qui modifient le résultat. Par exemple, une réponse de catalogue peut dépendre de la langue, de la devise, de la région et de la version des données. Incluez ces éléments de manière stable et lisible pour faciliter le diagnostic ; évitez d’enregistrer des informations sensibles dans la clé.
Si le résultat dépend de l’utilisateur, de son rôle, de ses autorisations ou de son organisation, l’isolation doit en tenir compte. Une clé qui ne comprend que le nom de la route peut faire parvenir une réponse personnalisée à une autre personne. Vérifiez également comment les entrées sont partagées entre les processus et les serveurs. Si vous ne pouvez pas énumérer de manière fiable toutes les dimensions qui affectent le résultat, ne stockez pas cette réponse dans un cache partagé.
La durée d’expiration doit répondre à une règle métier, et non correspondre à une valeur arbitraire. Une configuration qui change rarement peut tolérer une durée plus longue que le solde d’un compte ou l’état d’une réservation. Définissez la durée maximale acceptable d’obsolescence et envisagez de faire varier aléatoirement les expirations lorsque de nombreuses entrées similaires risquent d’expirer en même temps.
L’expiration temporelle ne remplace pas l’invalidation en cas de changements importants. C’est une limite supérieure qui empêche une entrée de persister indéfiniment, et non une garantie de mise à jour immédiate.
Mettre à jour et invalider lorsque la source change
Choisissez un mécanisme adapté au besoin de cohérence. L’invalidation explicite peut être exécutée après une écriture ; elle est simple, mais peut échouer si le processus est interrompu entre l’enregistrement de la donnée et la suppression du cache. Une autre possibilité consiste à utiliser des versions dans les clés : lorsque la source change, la version est incrémentée et les anciennes entrées ne sont plus consultées. Cela exige de gérer correctement cette version.
Dans les systèmes événementiels, un changement confirmé peut publier une notification afin d’invalider ou de recalculer les données dérivées. Si la livraison des événements n’est pas fiable, prévoyez des tentatives, l’idempotence et un mécanisme de réconciliation. Ne supposez pas que la mise à jour de la base de données et celle du service de cache constituent une opération atomique.
Pour les données qui tolèrent une courte période d’obsolescence, il peut être approprié de servir une entrée expirée pendant sa mise à jour en arrière-plan. Cette technique ne convient pas à toutes les informations : précisez quelles données sont admissibles, combien de temps l’obsolescence peut se prolonger et ce qui se passe si la mise à jour échoue. La décision doit dépendre des conséquences de l’affichage d’une ancienne valeur.
Définir un comportement sûr en cas de défaillance
Testez trois états distincts : entrée absente, entrée expirée et backend indisponible. Pour chacun, décidez si l’application recalcule la valeur à partir de la source, renvoie une erreur contrôlée ou, lorsque cela est sûr, fournit une ancienne valeur. Un cache vide doit être un état normal au démarrage et ne pas provoquer de résultats incorrects.
Protégez la source en cas de panne du backend. Si chaque requête lance une requête coûteuse à l’expiration de la même clé, un afflux massif de charge peut se produire. Parmi les mesures possibles figurent la limitation du nombre de recalculs simultanés, la réutilisation temporaire de valeurs sûres ou l’application de limites et de délais d’attente. La solution dépend de la possibilité de servir une donnée obsolète et de la capacité de la source.
Enregistrez les erreurs, les latences et les échecs de lecture ou d’écriture sans inclure de valeurs privées. Le cache est généralement une dépendance de performance, pas une autorité en matière de données : si son indisponibilité doit interrompre une opération critique, cette décision doit être explicitement justifiée.
Valider la cohérence et les performances à l’aide de tests reproductibles
Comparez les scénarios avec un cache désactivé, froid et chaud. Incluez la première requête après une écriture, les changements de langue ou d’autorisations, les expirations simultanées et la panne du backend. Vérifiez à la fois le contenu et l’isolation : deux utilisateurs disposant d’autorisations différentes ne doivent pas recevoir les réponses l’un de l’autre.
Utilisez des tests automatisés pour les règles importantes concernant les clés et l’invalidation, ainsi que des tests d’intégration pour vérifier le comportement avec le backend réel ou une solution de remplacement représentative. En charge, surveillez les succès et les échecs, la latence du cache, les opérations de recalcul, la charge de la source et les erreurs. Un taux de succès élevé ne prouve pas que les réponses sont correctes.
Lors du déploiement d’un changement, comparez les métriques et les erreurs à une référence. Prévoyez un moyen de désactiver l’optimisation ou de revenir à un comportement sûr si des données obsolètes, une hausse de la consommation mémoire ou une pression inattendue sur la base de données apparaissent.
Liste de contrôle pour l’exploitation du cache

- Problème mesuré : les routes et les opérations qui justifient le cache sont connues.
- Données et source définies : le cache n’est pas considéré comme le registre primaire.
- Clé complète : elle inclut les dimensions fonctionnelles et les autorisations pertinentes.
- Expiration justifiée : elle correspond à la tolérance métier à l’obsolescence.
- Invalidation prévue : l’événement qui met à jour ou remplace chaque entrée est spécifié.
- Défaillances couvertes : le comportement en cas de cache vide, expiré ou indisponible est défini.
- Mesure opérationnelle : la latence, les erreurs, les succès et la charge de la source sont surveillés.
- Tests d’isolation : les utilisateurs, rôles, langues et autres contextes pertinents sont validés.
Une stratégie de cache solide réduit le travail répétitif sans modifier involontairement le sens des données. Si chaque entrée a une portée claire, une politique de durée de validité et un plan de défaillance vérifiable, l’équipe peut évaluer ses bénéfices et supprimer ou ajuster l’optimisation lorsqu’elle cesse d’être adaptée.



