Aller au contenu principal
Site en cours de refonte — quelques pages peuvent bouger ou évoluer.
13 mars 2026

Cloudflare ne te “sauvera” pas d’un backend lent : passer un TTFB de 1,8s à <500ms (sans mythes)

Si ton HTML revient tout le temps à l’origine, Cloudflare est juste un proxy joli. Voilà comment diagnostiquer MISS/DYNAMIC et remettre du cache utile.

9 min de lecture
16 vues
réactions
Partager :
Cloudflare ne te “sauvera” pas d’un backend lent : passer un TTFB de 1,8s à <500ms (sans mythes)

Si ton TTFB est à 1,8s avec Cloudflare activé, j’ai une mauvaise nouvelle et une bonne. La mauvaise : Cloudflare ne fait pas de magie, il exécute ce que tu lui demandes. La bonne : dans beaucoup de cas, tu n’as pas un “problème Cloudflare”, tu as un problème de cache HTML. Et quand tu le règles proprement, passer sous 500ms (voire beaucoup moins sur les pages publiques) devient réaliste.

Le scénario classique ressemble à ça : le site est derrière Cloudflare, mais cf-cache-status alterne entre MISS et surtout DYNAMIC, et côté origin tu vois un cache-control: max-age=300 accompagné d’un must-revalidate. Résultat : Cloudflare revalide ou repasse à l’origine tout le temps. Donc ton PHP/CMS se refait le boulot à chaque visite. Et ton LCP mobile prend cher.

Cloudflare ne réduit le TTFB que si la réponse sort du cache edge

Ça vaut le coup de le dire sans détour : si la page HTML n’est pas servie depuis le cache Cloudflare, ton TTFB est surtout la latence + le temps serveur. Cloudflare accélère un peu le TLS, évite quelques kilomètres au navigateur, compresse parfois mieux… mais tu ne passes pas de 1,8s à 500ms “par chance”. Tu passes à 500ms quand l’edge répond sans demander à ton backend de recalculer la page.

Donc avant de toucher à la moindre règle, le premier réflexe c’est de prouver ce qui est réellement caché. Sinon tu vas bricoler des TTL au pif et tu ne sauras même pas si tu as gagné pour de vrai ou si tu as juste bougé un chiffre dans un dashboard.

Prouver ce qui est caché (et ce qui ne l’est pas)

Tu peux faire ça en 30 secondes avec un curl sur une page publique. L’idée : regarder les headers Cloudflare, et surtout ce que l’origine raconte via Cache-Control, Set-Cookie et Vary.

# 1) Un hit “normal”
curl -s -o /dev/null -D - https://exemple.com/landing \
  | egrep -i 'HTTP/|cf-cache-status|cache-control|age|vary|set-cookie|server-timing|cf-ray'

# 2) Un second hit immédiat (utile pour voir si tu obtiens HIT/AGE)
curl -s -o /dev/null -D - https://exemple.com/landing \
  | egrep -i 'HTTP/|cf-cache-status|cache-control|age|vary|set-cookie|server-timing|cf-ray'

Ce que tu veux voir sur une page que tu espères “cacheable”, c’est un cf-cache-status: HIT (ou parfois REVALIDATED si tu es sur un modèle avec revalidation) et un header Age qui monte. Si tu vois DYNAMIC en permanence, Cloudflare est en train de te dire : « je ne cache pas ça ».

Petit piège : un MISS n’est pas forcément grave, c’est souvent juste le premier hit. Ce qui est grave, c’est un MISS qui ne devient jamais HIT, ou un DYNAMIC partout, ou un BYPASS parce qu’un cookie traîne.

Pourquoi Cloudflare te répond DYNAMIC (les causes vraiment fréquentes)

Dans 80% des cas, ce n’est pas “Cloudflare qui bug”, c’est ton origine qui envoie des signaux qui empêchent le cache. Le coupable n°1, c’est Set-Cookie sur des pages publiques. Beaucoup de CMS posent un cookie “innocent” (session, tracking interne, consent, A/B test maison) sur des pages qui n’en ont pas besoin. Cloudflare voit un cookie et se dit : « ok, potentiellement personnalisé ». Et il ne met pas en cache, ou il segmente d’une façon qui te donne zéro hit.

Le coupable n°2, c’est un Cache-Control contradictoire. Par exemple max-age=300 avec must-revalidate et une logique d’ETag/Last-Modified qui force des allers-retours. Sur le papier, ça “cache 5 minutes”. En pratique, selon ta config Cloudflare et les règles, tu peux surtout déclencher des revalidations et retomber sur l’origine au pire moment (pile quand tu as du trafic).

Le coupable n°3, c’est Vary. Un Vary: User-Agent ou Vary: * mal maîtrisé, c’est une fragmentation de cache qui peut réduire ton hit rate à néant. Un Vary: Accept-Encoding est normal. Le reste mérite une vraie justification.

Fixer l’origine : enlever les “anti-cache” qui te sabotent

Je préfère le dire comme je le fais en prod : avant d’aller poser des Cache Rules “agressives”, commence par arrêter de tirer une balle dans le pied à l’origine.

Première action très rentable : arrêter de poser des cookies sur les pages publiques. Si ton CMS pose une session dès la première page vue “juste au cas où”, tu perds la bataille. L’objectif est simple : sur une landing anonyme, pas de Set-Cookie. Si tu as besoin d’un cookie pour la personnalisation, assume que cette page n’est pas cacheable, ou découpe la personnalisation en AJAX/ESI-like (et tu caches le HTML quand même).

Deuxième action : remettre de la cohérence dans Cache-Control. Pour une page HTML publique, tu veux un signal clair. Typiquement, côté origin, je préfère des directives qui jouent bien avec un CDN : s-maxage (pour les caches partagés), éventuellement stale-while-revalidate si tu sais ce que tu fais, et un TTL qui n’est pas ridicule. 300 secondes, c’est rarement une stratégie, c’est souvent un compromis “peur de servir du vieux”. Si tu as un mécanisme de purge, tu peux monter beaucoup plus haut.

Troisième action : vérifier les pages qui sortent en no-store ou private “par défaut”. Il y a des stacks qui ajoutent ça par sécurité. Très bien pour un espace client. Complètement contre-productif pour une page marketing qui devrait être stable et cacheable.

Mettre du cache HTML avec Cloudflare (quand c’est safe)

Le truc qui fait gagner gros sur un TTFB à 1,8s, c’est de cacher l’HTML des pages publiques. Pas seulement les assets. Les images et le JS sont déjà faciles à cacher et ne règlent pas ton TTFB serveur.

Avec Cloudflare, ça passe souvent par des Cache Rules qui disent explicitement : « pour telle partie du site, je cache, même si c’est du HTML ». Tu peux appeler ça “Cache Everything” dans l’ancien monde, ou le faire proprement via des règles modernes. Le principe reste le même : tu identifies des URLs vraiment publiques (landing pages, articles, pages catégories), et tu donnes à Cloudflare le droit de les servir depuis l’edge.

Le point clé, c’est de ne pas faire ça “site-wide” comme un bourrin si ton site a de la personnalisation. Sinon tu vas te retrouver à servir des pages connectées à des gens pas connectés, ou l’inverse. Et là tu n’as pas “optimisé”, tu as créé un incident.

Le bypass intelligent : login, panier, admin, pages personnalisées

Le cache HTML, c’est un scalpel, pas un rouleau compresseur. Tu caches agressivement ce qui est vraiment public, et tu bypass le reste. Concrètement, dès que tu as une zone de login, un panier, un backoffice, une page “mon compte”, ou même une page qui change selon la géoloc/AB test/cookie, tu assumes qu’elle doit bypass ou être cachée selon une clé claire (ce qui est plus compliqué).

Sur un CMS PHP, il y a souvent un indice simple : si la page est censée être identique pour tout le monde, elle doit rester sans cookie et cacheable. Si elle a besoin d’un cookie, elle n’est plus universelle. À partir de là, tu choisis : soit tu la sors du cache, soit tu refactores pour que seule une petite partie soit dynamique.

Mesurer sans se raconter d’histoires : edge vs origin, p95, et “premier hit”

Quand tu annonces “on est passé sous 500ms”, je veux toujours savoir : tu parles de quel percentile, et sur quel chemin. Le cache edge peut te donner un TTFB très bas sur le hit cache, tout en gardant un “premier hit” catastrophique si l’origine est lente et si tu as du trafic en dents de scie.

Regarde les métriques côté Cloudflare (cache hit ratio, statut de cache), mais garde aussi une mesure qui te ramène à la vérité : temps de réponse origin, TTFB sur HIT et sur MISS, et idéalement un p95. Si ton p50 est magnifique et ton p95 est horrible, tu as souvent un problème de “dogpile” (tout le monde retombe sur l’origine quand le cache expire) ou un TTL trop court combiné à un backend instable.

Un bon signe que tu es sur la bonne voie : tes pages publiques passent majoritairement en HIT et ton origin respire. Pas l’inverse.

Le faux gain : le cache qui casse la personnalisation, le tracking, ou le SEO

Oui, un cache mal réglé peut faire du dégât SEO. Pas parce que “Google n’aime pas le cache”, mais parce que tu peux servir une version incohérente. Le cas le plus bête : des balises canonical/hreflang qui changent selon des paramètres, et tu caches une version qui fuit vers une autre. Ou un système qui injecte du contenu selon un cookie et tu caches l’injection.

Mon approche : je préfère perdre 50ms et garder un comportement déterministe que gagner 300ms et faire de la roulette. Le cache HTML doit s’appuyer sur une règle produit claire : quelles pages sont publiques, identiques, et peuvent être purgées proprement. Si tu n’as pas cette réponse, commence par là. Cloudflare ne décidera pas à ta place.

Si malgré tout tu as encore 1,8s : Cloudflare n’est plus le sujet

Une fois que tu as du HIT sur les pages publiques, si tu as encore un TTFB haut, là on reparle “vrai backend”. PHP-FPM sous-dimensionné, DB lente, DNS interne, appels externes, surcharge CPU, disque qui rame, plugins qui font n’importe quoi. Cloudflare n’a jamais été censé cacher ça sur des pages dynamiques.

Mais dans le cas typique qui motive cet article, tu n’en es même pas là. Tu as surtout un cache désactivé par des cookies et des headers incohérents, et tu es en train de demander à un CDN de corriger une page que tu ne lui laisses pas cacher. Ça ne marche pas.

Sources

Cet article vous a plu ?

Commentaires

Laisser un commentaire

Entre 10 et 2000 caractères

Les commentaires sont modérés avant publication.

Aucun commentaire pour le moment.

Soyez le premier à donner votre avis !