Quand je dois optimiser la latence d’une application web en production, j’adopte une approche pragmatique et mesurable : mesurer d’abord, corriger les plus gros goulets d’étranglement, et automatiser pour que les gains tiennent dans la durée. Dans mes projets récents j’ai combiné nginx en tant que reverse-proxy/terminaison TLS, Cloudflare pour la distribution au bord et la sécurité, et Varnish pour le cache applicatif hautes performances. Voici mon retour d’expérience concret, avec des configurations et des checks faciles à appliquer.

Mesurer avant d’agir

On ne peut pas améliorer ce qu’on ne mesure pas. Mes indicateurs favoris :

  • TTFB (Time To First Byte)
  • First Contentful Paint / Largest Contentful Paint pour la partie front
  • Percentiles de latence (p50, p95, p99)
  • Requests per second et erreurs 5xx
  • Outils que j’utilise quotidiennement : curl -I, wrk, hey, WebPageTest, Lighthouse et les métriques côté serveur (Prometheus + Grafana). Un exemple rapide pour mesurer le TTFB :

    curl -w "@curl-format.txt" -o /dev/null -s https://www.monsite.fr/

    Mon fichier curl-format.txt contient des timings utiles comme %{time_starttransfer} qui correspond au TTFB.

    Architecture cible : nginx + Varnish + Cloudflare

    Voici l’idée générale que j’applique :

  • Cloudflare en frontal pour CDN, TLS (1.3), HTTP/3/QUIC, WAF et cache edge
  • nginx comme terminateur TLS si besoin d’un contrôle fin (ou directement Cloudflare Origin Certificate)
  • Varnish entre nginx et l’application pour un cache HTTP rapide et configurable
  • Avantages : Cloudflare réduit la distance physique, Varnish gère les règles de cache complexes et la purge fine, nginx assure la terminaison TLS, les en-têtes et la compression.

    Configurer Cloudflare pour réduire la latence

  • Activer HTTP/2 et HTTP/3 — récupération d’assets plus rapide et multiplexing
  • Utiliser le mode “Cache everything” pour les pages statiques ou là où l’interface le permet (attention aux pages personnalisées)
  • Activer Brotli et la compression côté edge
  • Configurer des Page Rules pour étendre la durée de cache des ressources immuables (images, JS/CSS avec hash dans le nom)
  • Activer Argo Smart Routing pour certains cas (réduit latence réseau entre clients et data centers Cloudflare)
  • Vérifier CF-Cache-Status dans les réponses pour s’assurer qu’on sert depuis le cache edge
  • Astuce : utilisez les Origin Certificates de Cloudflare pour sécuriser la connexion Cloudflare → origine sans exposer un certificat public — cela simplifie la terminaison TLS côté serveur.

    nginx : réglages pratiques

    Quand nginx est exposé ou qu’il est le reverse-proxy entre Cloudflare et Varnish, voici mes optimisations clés :

  • Activer keepalive entre nginx et l’application / Varnish : keepalive_timeout 65;
  • Ajuster les buffers pour réduire les system calls : client_body_buffer_size 16K; et client_max_body_size selon vos besoins
  • Activer gzip + Brotli (si vous avez un module) : compression des assets textuels
  • Utiliser sendfile, tcp_nopush, tcp_nodelay : sendfile on; tcp_nopush on; tcp_nodelay on;
  • Limiter les logs en production sur les endpoints très chauds pour éviter I/O blocking
  • Exemple simplifié (bloc http) :

    sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; gzip on; gzip_types text/plain application/json text/css application/javascript;

    Varnish : mise en cache applicatif efficace

    Varnish est excellent pour réduire la charge applicative et baisser le TTFB quand on sert beaucoup de contenu dynamique mais cacheable.

  • Utiliser VCL pour définir les règles : quels chemins cache-t-on, pour combien de temps, et comment purger
  • Mettre en place un système de purge/purge by surrogate-key (Header « Surrogate-Key ») pour purger finement
  • Configurer grace pour servir du contenu légèrement expiré en cas de problématique backend (stale-while-revalidate)
  • Surveiller hit/miss et eviction pour ajuster la taille mémoire : varnishstat
  • Exemple VCL simple :

    sub vcl_recv { if (req.url ~ "^/api/") { return (pass); } else { return (hash); } }sub vcl_backend_response { set beresp.ttl = 10m; set beresp.grace = 1h; }

    Headers et politique de cache

    Les headers contrôlent le comportement du cache :

  • Cache-Control: public, max-age=..., s-maxage=... (s-maxage pour caches partagés comme Cloudflare/Varnish)
  • Surrogate-Control / Surrogate-Key pour Varnish
  • Vérifier et propager Age, Via, CF-Cache-Status
  • Un exemple d’en-tête pour une page coté serveur :

    Cache-Control: public, max-age=60, s-maxage=600, stale-while-revalidate=30

    Stratégies de purge et invalidation

    Purger tout le cache est tentant mais coûteux. J’utilise :

  • Purge par clé (surrogate key) pour les assets liés à un article/ressource
  • Purge automatique à la mise en prod via pipeline CI (ex: appeler l’API de Cloudflare et le endpoint de purge Varnish)
  • Utiliser le header ETag / Last-Modified pour validations conditionnelles
  • Optimisations réseau et TLS

  • Activer TLS 1.3 — réduit les handshakes
  • OCSP Stapling pour éviter des allers-retours supplémentaires
  • Activez TCP Fast Open si votre OS et stack le supportent
  • Réduire la latence DNS : utilisez un service DNS rapide et configurez un TTL adapté
  • Métriques & Monitoring continus

    Après avoir appliqué les optimisations, je configure des dashboards qui suivent :

  • TTFB global et par endpoint
  • Taux de hit cache Cloudflare/Varnish
  • Latence p95/p99 et erreur 5xx
  • Utilisation mémoire/CPU de Varnish et nginx
  • Quelques commandes utiles :

  • varnishstat — pour voir hit/miss
  • varnishlog — pour debug
  • curl -I -H "Cache-Control: no-cache" — pour forcer un bypass et tester l’origine
  • Quelques pièges à éviter

  • Ne pas cacher des pages personnalisées (ex : tableau de bord utilisateur) sans mécanisme de personnalisation
  • Ne pas oublier les cookies — ils rendent souvent la réponse non-cacheable si mal gérés
  • Purger trop souvent le cache → perte d’efficacité
  • Ignorer les assets versionnés (hash in filename) — sans versionning, impossible d’avoir un cache long en sécurité
  • Cas pratique rapide

    Sur un projet e‑commerce, en combinant :

    AvantAprès
    TTFB moyen 450msTTFB moyen 90ms
    Charge CPU backend élevéeBackend réduit de 70% de charge
    Cache hit 15%Cache hit 85% (Cloudflare + Varnish)

    Les actions : mise en place de Varnish avec surrogate-keys, configuration Cloudflare “Cache everything” pour pages standards, optimisation nginx (keepalive, sendfile) et compression Brotli. Mes clients ont senti la différence, surtout sur les pages produits très visitées.

    Si vous voulez, je peux vous fournir des snippets de configuration plus détaillés (nginx.conf, vcl.vcl) adaptés à votre architecture, ou vous guider pour intégrer la purge automatique dans votre CI/CD. Dites-moi quelle stack exacte vous utilisez et je vous envoie des exemples personnalisés.