Comment bien choisir de cache

Tu le sais probablement déjà : le cache HTTP peut transformer un site lent en une expérience quasi instantanée. Pourtant, dans la majorité des projets que j’audite, les en-têtes de cache sont soit absents, soit tellement mal réglés qu’ils font plus de mal que de bien. J’ai vu un site perdre 30 % de ses visiteurs à cause d’une expiration trop longue sur des ressources dynamiques.

Prenons un exemple concret : tu déploies une nouvelle version de ton application, mais tes fichiers CSS sont encore en cache pour une semaine. Résultat : des bugs visuels pour tes utilisateurs, et toi tu passes des heures à essayer de comprendre pourquoi. La solution ? Configurer correctement Cache-Control et utiliser des ETags pour la validation conditionnelle.

Dans ce guide, je vais te montrer les différents types de cache (navigateur, serveur, CDN), comment régler les en-têtes comme Cache-Control et Expires sans te tromper, et pourquoi les ETags sont tes meilleurs alliés pour éviter les requêtes inutiles. On verra aussi quand il faut sortir l’artillerie lourde avec un CDN comme CloudFront, ou des solutions de cache serveur comme Varnish ou Redis. Le but : t’aider à choisir une stratégie de cache adaptée à tes besoins, pour des performances au top et zéro casse.

Comprendre les différents types de cache HTTP

Le cache de ton navigateur, c'est le plus visible, mais pas le plus important. Les fichiers CSS, JS, images y sont stockés localement pour éviter de les retélécharger à chaque visite. Tu le configures avec Cache-Control et Expires. Mais attention : si tu mets une durée trop longue sur des ressources dynamiques, tu vas te retrouver avec des versions obsolètes chez tes utilisateurs. Moi, je garde ça pour les assets statiques versionnés.

Ensuite, il y a le cache proxy. Je parle des CDN comme CloudFront ou Cloudflare, mais aussi des reverse proxy comme Varnish installé devant ton serveur. Le principe : une couche intermédiaire qui sert les réponses mises en cache depuis un point d'accès proche de l'utilisateur. Sur un site que j'ai audité, le fait de placer Varnish devant l'application a divisé le temps de réponse par 4 pour les pages les plus populaires.

Enfin, n'oublie pas le cache applicatif. Redis, Memcached, ou même le cache interne de ton framework. C'est lui qui évite de refaire des calculs lourds, comme des requêtes SQL complexes. Typiquement, quand tu fais une recherche longue à générer, tu stockes le résultat dans Redis avec une expiration courte. En combinant ces trois niveaux, tu couvres tous les cas d'usage : rapidité pour l'utilisateur, charge réduite pour ton serveur.

Configurer les en-têtes HTTP pour le cache

La plupart des sites que j’audite ont des en-têtes Cache-Control soit absents, soit configurés au petit bonheur la chance. Résultat : soit les ressources ne sont jamais mises en cache, soit elles le sont trop longtemps. Pourtant, avec deux lignes de configuration, tu peux régler ça proprement.

Pour Cache-Control, tu définis une politique avec des directives : max-age pour la durée en secondes, public ou private selon qui peut mettre en cache, et no-cache si tu veux forcer la validation côté serveur. Exemple typique sur mes assets versionnés : Cache-Control: public, max-age=31536000, immutable. Ce n’est pas une science exacte, mais ça évite 90 % des problèmes.

La grosse différence entre Cache-Control et Expires, c’est que le premier est plus flexible et prioritaire. Expires utilise une date absolue (ex: Expires: Wed, 21 Oct 2025 07:28:00 GMT) et devient obsolète une fois passée. Cache-Control avec max-age gère une durée relative et te permet d’autres directives. Mon conseil : utilise Cache-Control en standard, et ajoute Expires seulement pour compatibilité avec de vieux proxies ou navigateurs (HTTP/1.0).

Un cas concret : sur un projet récent, un collègue avait configuré Expires avec une date fixe pour toutes les pages. Résultat : au bout du délai, tout le cache était invalidé en même temps, provoquant une charge énorme sur le serveur. Avec Cache-Control: no-cache sur les pages dynamiques et max-age adapté à chaque type de ressource, la charge a été lissée.

N’oublie pas non plus les en-têtes de validation comme ETag ou Last-Modified. Ils permettent au navigateur de demander une ressource et de ne la retélécharger que si elle a changé. Combine Cache-Control: no-cache avec un ETag fort, et tu obtiens une validation conditionnelle ultra-efficace. En pratique, je mets toujours un ETag sur les réponses HTML et JSON.

Optimiser avec les ETags pour la validation conditionnelle

Les ETags sont l'arme secrète pour éviter les transferts inutiles. J'ai vu un site économiser 40% de bande passante en les configurant correctement sur ses API JSON. Le principe est simple : le serveur associe un identifiant unique (souvent un hachage) à chaque version d'une ressource via l'en-tête ETag. Le client le renvoie dans If-None-Match lors de sa prochaine requête. Si le contenu n'a pas changé, le serveur répond avec un statut 304 Not Modified, sans retransmettre le body.

Prenons un exemple concret avec une API Node.js/Express. J'utilise le package etag pour générer automatiquement un ETag basé sur le contenu. Résultat : quand un client fait une requête avec un ETag valide, la réponse passe de 200 avec 50 Ko de JSON à un simple 304 de quelques centaines d'octets. La différence est flagrante sur les connexions mobiles. Voici comment je le configure :

Je désactive Last-Modified ici parce que je préfère m'appuyer uniquement sur les ETags, plus précis. Mais tu peux combiner les deux si tu veux une couche de validation supplémentaire.

Mon conseil : utilise toujours un ETag fort (basé sur le contenu) plutôt qu'un ETag faible. Les ETags faibles (avec préfixe W/) sont utiles pour des représentations sémantiquement équivalentes, mais pour des performances optimales, un ETag fort est plus fiable. Évite aussi de t'appuyer sur l'inode ou la date de modification dans un environnement distribué – tu risquerais des incohérences entre plusieurs serveurs.

Enfin, n'oublie pas de coupler les ETags avec un Cache-Control approprié. Si tu paramètres un max-age trop court, le client va systématiquement revalider, ce qui réduit l'intérêt de la mise en cache. Moi, je mets un max-age de 0 sur les ressources dynamiques avec un ETag fort : le client doit toujours revalider, mais il ne retransfère les données que si elles ont changé. C'est le meilleur compromis entre fraîcheur et bande passante.

Intégrer un CDN pour amplifier les performances

J'ai vu un site réduire son temps de chargement de 60% juste en ajoutant un CDN devant un bucket S3. Pourtant, tout le monde n'en a pas besoin. Moi, je réserve le CDN pour les projets où l'audience est répartie géographiquement ou quand le serveur peine sous la charge.

Prenons un cas concret : un site e-commerce avec des visiteurs en Europe et aux États-Unis. Sans CDN, les utilisateurs américains attendaient 3 secondes de plus à cause de la latence. En plaçant CloudFront devant, le temps de réponse est passé de 2,5 s à 0,8 s pour eux. En prime, le taux de cache hit a atteint 85%, ce qui a divisé par 5 les requêtes vers l'origine. Pour que ça marche, j'ai configuré Cache-Control avec public, max-age=31536000 sur les assets statiques versionnés, et no-cache sur les pages dynamiques. Le CDN respecte ces en-têtes et ne met en cache que ce que tu l'autorises.

Attention : un CDN n'est pas une solution magique. Si ton site n'a que des visiteurs locaux et que ton serveur tient la charge, tu n'en tireras aucun bénéfice. Pire, tu ajoutes une complexité inutile. Mon conseil : commence par bien régler ton cache serveur et navigateur. Si tu vois que tu perds du temps sur la latence réseau ou que tu as des pics de trafic, alors sors l'artillerie lourde avec un CDN. CloudFront, Cloudflare ou Fastly ? Peu importe, tant que tu respectes les bonnes pratiques de cache.

Conclusion

Tu penses peut-être que le cache HTTP c'est un détail technique ? J'ai vu des sites passer de 3 secondes à 800 ms juste avec une bonne politique de cache. C'est souvent le levier le plus simple pour améliorer les performances.

Sur mon dernier projet e-commerce, j'ai combiné un cache navigateur de 7 jours pour les assets versionnés, un cache CDN de 10 minutes pour les pages produits, et Redis pour les sessions. Résultat : 40 % de trafic en moins sur le serveur applicatif. Ce n'est pas magique, c'est de la configuration réfléchie.

Le choix de ta stratégie dépend de ton contexte. Si tu as une API avec des données qui changent toutes les 5 minutes, un max-age de 5 minutes avec validation ETag est idéal. Si tu sers des images statiques, mets-les en cache pour un an avec des noms versionnés. Ne tombe pas dans le piège de mettre des temps d'expire trop longs sur des ressources dynamiques. J'ai déjà vu un site avec une page d'accueil mise en cache pour 24h : les utilisateurs voyaient des informations obsolètes. Préfère la validation conditionnelle (ETag/Last-Modified) pour les ressources qui changent régulièrement.

En résumé, les performances de ton application passent par une configuration réfléchie du cache. Commence par auditer tes en-têtes actuels. Ensuite, choisis une combinaison cohérente entre cache navigateur, cache CDN et cache applicatif. Et surtout, teste tes changements pour éviter les mauvaises surprises.

Pour ma part, je configure toujours au minimum Cache-Control et ETag sur toutes mes réponses HTTP. C'est la base. Le reste (Expires, CDN) vient en fonction du besoin. Mais je ne laisse jamais un en-tête de cache par défaut : ça finit toujours par faire des dégâts.

Link_