Quand toutes vos optimisations ne suffisent plus
OPcache, Redis, requêtes SQL ajustées, queues asynchrones… vous avez appliqué le manuel de performance Laravel et votre TTFB reste à 600 ms depuis l'étranger. La raison est simple : chacune de ces techniques optimise une requête qui doit quand même traverser votre réseau, démarrer le framework et rendre une vue. Le cache HTML full-page à la bordure du réseau (edge caching) supprime cette requête côté serveur. Le visiteur reçoit le HTML final depuis un datacenter Cloudflare à quelques millisecondes, et votre origine n'est jamais sollicitée.
Pourtant, presque aucune équipe Laravel ne l'implémente. La raison : Laravel touche la session sur presque chaque requête web et répond avec un en-tête Set-Cookie. Or tout cache partagé bien configuré refuse de stocker une réponse qui pose un cookie. Résultat : tout reste DYNAMIC, et vous payez des ressources serveur pour du contenu souvent statique.
Cet article est adapté d'un retour d'expérience publié sur dev.to par Web Pioneer, déployé en production sur web-pioneer.com.
L'architecture : l'origine décide, l'edge obéit
Le principe directeur : la logique de mise en cache vit dans l'application Laravel, pas dans le tableau de bord Cloudflare. Cloudflare reçoit une seule instruction simple : « cache le HTML quand l'origine l'autorise ».
Cela passe par un middleware Laravel, baptisé EdgeCache, qui est le seul à savoir :
- si la page courante est cacheable (contenu public, non personnalisé),
- si l'utilisateur est authentifié ou porte un cookie de session actif,
- quelles routes ou conditions excluent définitivement le cache.
Ce middleware émet des en-têtes HTTP qui pilotent Cloudflare en aval.
Les en-têtes qui font tout le travail
// Réponse cacheable par Cloudflare, pas par le navigateur
Cache-Control: public, s-maxage=3600, max-age=0
// Variante selon les cookies présents
Vary: Cookie
L'en-tête s-maxage cible uniquement les caches partagés (comme Cloudflare) ; max-age=0 empêche le navigateur de cacher localement une page potentiellement personnalisée. Vary: Cookie indique au cache que deux requêtes avec des cookies différents doivent être stockées séparément.
Exclure les sessions sans les casser
Le problème central reste le cookie de session Laravel. La solution : ne pas démarrer la session sur les routes cacheables. Cela implique de restructurer le stack de middlewares :
// Dans un groupe de routes public (blog, landing pages, etc.)
Route::middleware([
EdgeCache::class, // avant StartSession
// StartSession retiré volontairement
])->group(function () {
Route::get('/blog/{slug}', [ArticleController::class, 'show']);
});
Pour les routes qui ont besoin à la fois du cache et d'un état utilisateur minimal (panier, préférences), on peut passer par un cookie first-party dédié, séparé du cookie de session Laravel, et l'exclure de la logique de Vary.
Configurer Cloudflare côté serveur
Cloudflare, par défaut, ne cache pas le HTML. Il faut créer une règle de cache personnalisée (Cache Rule) dans le tableau de bord :
- Critère :
URI Pathcorrespond à vos routes publiques (ouContent-Typecontienttext/html). - Action : Respect origin Cache-Control headers — Cloudflare suit alors ce que votre middleware envoie.
- Bypass si cookie présent : ajoutez une condition d'exclusion sur le cookie de session Laravel (
laravel_session) pour ne jamais cacher une réponse personnalisée.
If cookie "laravel_session" exists → BYPASS
Else → Cache (respect origin headers)
Cette règle garantit que l'edge ne stocke jamais accidentellement une page authentifiée.
Invalidation : purger proprement
Le cache edge a une durée de vie (s-maxage), mais les contenus changent. Deux stratégies :
- TTL court (5 à 15 minutes) pour les contenus semi-dynamiques : simple, sans infrastructure supplémentaire.
- Purge sur événement : depuis un Observer Eloquent ou un job Laravel, appel à l'API Cloudflare pour invalider une URL précise après modification.
// Purge ciblée via l'API Cloudflare
Http::withToken(config('services.cloudflare.token'))
->delete("https://api.cloudflare.com/client/v4/zones/{$zoneId}/purge_cache", [
'files' => [url("/blog/{$article->slug}")],
]);
Cette approche permet des TTL longs (1 à 24 heures) sans risque de servir du contenu obsolète.
Les erreurs à éviter
L'expérience rapportée dans l'article source mentionne plusieurs pièges rencontrés en production :
- Oublier
Vary: Cookie: Cloudflare peut servir une page authentifiée à un visiteur anonyme si la variation n'est pas déclarée. - Cacher les réponses 404 ou 500 : toujours conditionner le cache à un statut HTTP 200.
- Ne pas tester avec un vrai CDN : les en-têtes
CF-Cache-Status(HIT, MISS, BYPASS) sont indispensables pour valider le comportement réel. Uncurl -Idepuis une machine distante suffit. - Mélanger logique de cache dans Cloudflare et dans Laravel : un seul endroit décide, l'autre exécute. La duplication crée des incohérences difficiles à déboguer.
# Vérifier le statut du cache Cloudflare
curl -sI https://example.com/blog/mon-article | grep -i cf-cache-status
# CF-Cache-Status: HIT
Conclusion
Le cache HTML full-page à l'edge n'est pas réservé aux architectures complexes. Avec un middleware Laravel ciblé, une règle Cloudflare correctement configurée et une stratégie d'invalidation adaptée à vos contenus, vous pouvez supprimer la majorité des requêtes vers votre origine — et offrir un TTFB sous les 50 ms à vos visiteurs, quelle que soit leur localisation.
La clé est de ne jamais déléguer la décision de cache à l'infrastructure : c'est l'application qui connaît le contexte métier, la session utilisateur, et les règles d'exclusion. Cloudflare n'est que l'exécutant fidèle.
Ce que ça change pour vous
Si vous gérez un site vitrine, un blog ou une boutique en ligne, cette technique signifie concrètement que votre site supporte dix ou cent fois plus de visiteurs simultanés sans changer de serveur ni augmenter votre budget hébergement. Les pages s'affichent en un clin d'œil, même pour des visiteurs au bout du monde. Lors d'un pic de trafic — après une newsletter ou un passage en presse — votre serveur reste serein, car Cloudflare absorbe les visites à sa place. Demandez à votre prestataire technique si vos pages publiques bénéficient déjà de cette mise en cache : la vérification prend cinq minutes et le gain peut être immédiat.
Et votre site, il vaut quoi ?
Vitesse, accessibilité, référencement technique. Le rapport est écrit pour un dirigeant, pas pour un développeur. Gratuit, sans inscription.