La page produit affiche l'ancien prix après une promo flash — le support accuse « le CDN ». En réalité, PHP envoie Cache-Control: public, max-age=3600 sur le HTML catalogue, Cloudflare respecte cette directive, et seule l'API panier renvoie no-store. Les assets JavaScript restent frais grâce au hash dans le nom de fichier ; le HTML catalogue, lui, reste figé une heure entière. Personne n'a documenté quelle couche met en cache quelle ressource.
Les headers HTTP de cache sont le contrat entre votre origin, le CDN et le navigateur. Mal alignés, vous payez plusieurs fois : latence pour l'utilisateur, surcharge de l'origin, ou contenu périmé qui fragilise la confiance. Un CDN activé sans politique cohérente ajoute une étape réseau sans en retirer le bénéfice.
La suite pose une matrice ressource par ressource — pas un slider « cache activé » dans le panel hébergeur.
Cache-Control : les directives qui comptent vraiment
Cache-Control est la directive la plus lue par les navigateurs et les CDN. Chaque mot-clé a un effet précis :
| Directive | Effet |
|---|---|
max-age=N | Ressource considérée fraîche N secondes côté navigateur |
s-maxage=N | Même logique, mais pour les caches partagés (CDN) |
no-store | Aucun stockage — données sensibles, pages de compte |
no-cache | Stockage autorisé, revalidation obligatoire avant usage |
immutable | Asset fingerprinté — pas de revalidation inutile |
stale-while-revalidate | Servir une version périmée pendant un rafraîchissement asynchrone |
Pour le HTML dynamique (catalogue, articles, pages personnalisées), privilégiez private, no-cache ou un max-age court couplé à une revalidation. Pour les assets statiques avec hash dans le nom (/app.abc123.js), public, max-age=31536000, immutable est le standard attendu.
Un CDN ne devine pas votre intention — il obéit aux headers, sauf règle d'override explicite dans le panel.
Sur un hébergement mutualisé ou un VPS avec CDN intégré (OVH, Infomaniak, etc.), vérifiez que les règles du panel ne contredisent pas ce que votre application envoie. Les conflits entre nginx, PHP et le CDN sont l'une des causes les plus fréquentes de contenu stale.
CDN, origin et le piège du header Vary
Le header Vary indique au cache quelles dimensions de la requête influencent la réponse. Deux cas reviennent sans cesse :
Vary: Accept-Encoding — indispensable si vous servez Brotli et gzip selon le client. Sans Vary, un CDN peut mettre en cache la version gzip et la servir à un client qui attend du Brotli.
Vary: Accept — nécessaire si vous négociez le format d'image (WebP, AVIF) via le header Accept. Sans Vary, le CDN peut servir un AVIF à un navigateur qui ne le supporte pas. Pour la stratégie complète, consultez WebP et AVIF.
Configurez la clé de cache côté CDN : incluez l'encodage, excluez les cookies de session sur les assets publics. Un Set-Cookie sur un fichier CSS peut empêcher la mise en cache edge chez certains fournisseurs.
ETag, réponses 304 et charge sur l'origin
La revalidation conditionnelle permet d'éviter de retélécharger un fichier inchangé. Le client envoie If-None-Match avec l'ETag reçu ; le serveur répond 304 sans corps si le contenu est identique.
En cluster multi-nœuds, un ETag généré par machine (inode, timestamp) devient incohérent : le client reçoit des 200 au lieu de 304, et l'origin reprend la charge. Préférez un hash de contenu stable, ou déléguez le cache au CDN avec des durées longues sur les assets fingerprintés.
Pour une API JSON utilisateur (/api/me, /api/orders), no-store ou un cache très court avec clé par utilisateur reste la norme. Un cache partagé CDN sur ces routes expose des données privées.
Stratégie par type de ressource
Chaque type de fichier mérite sa politique — documentée, testée, partagée avec l'équipe :
| Ressource | Politique recommandée |
|---|---|
| CSS/JS avec hash | 1 an, immutable |
| Images statiques | 7 à 30 jours + purge ciblée au déploiement |
| HTML public | max-age court + stale-while-revalidate, ou no-cache |
| API utilisateur | private, no-store |
| Feeds, sitemaps | Court max-age ou revalidation ETag |
Sous WordPress, des plugins modifient les headers sans coordination — auditez le filtre wp_headers et comparez ce que renvoient nginx, PHP-FPM et le CDN. Un plugin de cache page peut entrer en conflit avec un plugin de minification qui change les noms de fichiers.
Pour le déploiement et l'invalidation, croisez cette lecture avec HTTP/2 et multiplexage : moins de connexions ne compense pas des assets mal mis en cache.
Purge, déploiement et erreurs classiques
Trois erreurs reviennent à chaque audit :
- Oublier la purge CDN après un déploiement HTML non fingerprinté — le visiteur voit l'ancienne version pendant des heures.
Cache-Control: max-age=0sansno-store— comportement variable selon le CDN ; certains stockent quand même.- Cookies sur les assets —
Set-Cookiesur un fichier statique peut bloquer la mise en cache edge.
Testez systématiquement avec curl -I depuis l'edge CDN et depuis l'origin. Les headers doivent être identiques ou la différence doit être documentée (terminaison TLS au CDN, compression, etc.).
Comparez les offres avec CDN intégré via notre annuaire et le comparateur — certains hébergeurs imposent des règles par défaut qu'il faut connaître avant de déployer.
Le sommet : CDN activé, rien de cacheable
Voici ce que la checkbox « CDN activé » dans le panel ne dit pas.
Faire coopérer les trois couches, c'est accepter que chaque type de fichier a sa politique — pas un réglage global « cache on ».
Décider et avancer sans angle mort
Sur une demi-journée, vous pouvez remettre le cache sur des bases saines :
- Dressez une matrice ressource → directive (
Cache-Control,Vary, durée) et partagez-la avec l'équipe. - Fingerprintez les assets statiques (hash dans le nom) pour permettre des durées longues sans purge aveugle.
- Vérifiez les headers Vary si vous négociez compression ou format d'image.
- Testez avec
curl -Idepuis l'edge et l'origin — documentez les écarts attendus. - Planifiez une purge ciblée à chaque déploiement HTML, jamais un « purge everything » sans file d'attente de rollback.
- Comparez les hébergeurs avec CDN via l'annuaire si vous migrez ou renégociez votre stack.
Pour un audit rapide, prenez une URL HTML et un fichier JS — les headers doivent être cohérents entre les trois couches. Si vous hébergez déjà chez un acteur européen, consultez sa fiche sur Hébergeurs.eu pour connaître les règles CDN par défaut.
Questions fréquentes
public vs private vs no-store ?
public autorise le CDN à mettre en cache la réponse pour tous les visiteurs. private limite le stockage au navigateur de l'utilisateur — adapté aux pages de compte. no-store interdit tout stockage, y compris en mémoire, pour les données sensibles. no-cache permet le stockage mais exige une revalidation avant usage.
max-age et s-maxage ?
max-age s'applique au navigateur ; s-maxage aux caches partagés comme le CDN. Sur un asset versionné (/app.abc123.js), un max-age long couplé à immutable évite les requêtes inutiles. Le HTML dynamique mérite des durées courtes ou une revalidation systématique.
Comment invalider après deploy ?
Fingerprintez les fichiers (hash dans le nom), purgez le CDN de façon ciblée sur les URLs concernées, ou ajoutez un paramètre de version. Évitez la purge totale en production sans plan de rollback — elle peut saturer l'origin si tout le trafic repart en miss.
ETag ou Last-Modified ?
L'ETag permet une revalidation conditionnelle précise (réponse 304 sans corps). Last-Modified fonctionne aussi, mais l'ETag basé sur un hash de contenu est plus fiable en cluster. Attention aux ETag générés par machine — ils rendent la revalidation inefficace.
Le cache efficace se lit dans les headers — pas dans la checkbox CDN du panel hébergeur.