Magento performance : stack Nginx Varnish Redis Elasticsearch pour e-commerce

Guide pratique pour optimiser Magento 2.4+ : architecture Nginx, Varnish, Redis et Elasticsearch, stratégies de cache, gestion des sessions et observabilité pour réduire latence et charge.

Configuration technique de serveurs pour un site e-commerce performant.

Table des matières :

  1. Architecture de référence : qui fait quoi dans une stack Nginx + Varnish + Redis + Elasticsearch
  2. Nginx + PHP-FPM : réduire le coût de chaque miss (et éviter les faux goulots)
  3. Varnish : mettre Magento en cache sans casser le panier (ni l’indexation)
  4. Redis : sessions et cache applicatif Magento sans transformer Redis en point unique de panne
  5. Elasticsearch (ou OpenSearch) : latence de recherche, indexation, et dérives de ressources
  6. Dimensionnement, observabilité et rollout : prouver le gain (et éviter l’usine à gaz)

Architecture de référence : qui fait quoi dans une stack Nginx + Varnish + Redis + Elasticsearch

Sur Magento Open Source / Adobe Commerce 2.4.x (PHP 8.2+ en pratique en 2026), la performance ne se joue pas sur « un serveur plus gros » mais sur une séparation claire des rôles : Nginx termine TLS et sert le statique, Varnish absorbe le trafic anonyme via cache HTTP, Redis sort les sessions et les caches applicatifs de MySQL, et Elasticsearch (ou OpenSearch) externalise la recherche et une partie du filtrage. Le point à ne pas rater : la majorité des pages « catalog » (home, catégories, produits) peuvent être servies sans toucher PHP si votre stratégie de cache est cohérente, alors que checkout / compte / panier restent dynamiques.

Le flux « propre » ressemble à : Client → Nginx (TLS, HTTP/2, gzip/brotli, static) → Varnish (cache + invalidation) → Nginx backend (reverse proxy) → PHP-FPM (Magento) → MySQL + Redis + Elasticsearch. Cette topologie impose une discipline sur les headers (Cache-Control, Surrogate-Control), les cookies, et les règles de passage en pass côté Varnish. Si vous ne maîtrisez pas précisément ce qui est cachable, vous finirez avec un Varnish qui enregistre peu de hits et une stack plus complexe sans gain.

Pour éviter les malentendus, voici une lecture « qui fait quoi » très opérationnelle :

Brique Rôle principal Ce qu’elle ne doit pas faire Indicateur de santé utile
Nginx (front) TLS, HTTP/2, compression, statique, reverse proxy Exécuter PHP, servir du contenu dynamique lourd taux 499/504, upstream_response_time
Varnish Cache HTTP (HTML/JSON) + grace + invalidation Décider de la logique métier, cacher du contenu personnalisé hit ratio, backend_fail, cache_hit
PHP-FPM + Magento Générer HTML/JSON, business logic Servir statique, recalculer des pages cachables p95/p99 dynamiques, saturation workers
Redis Sessions + cache applicatif + verrous Remplacer MySQL, absorber des volumes sans limites evictions, mémoire, latence
Elasticsearch/OpenSearch Recherche, autosuggest, facettes (agrégations) Servir « comme une DB relationnelle » latence requêtes, heap/GC, saturation CPU

Trois définitions utiles, parce que Magento mélange souvent les concepts : (1) le cache HTTP (Varnish) met en cache des réponses complètes (HTML/JSON) indexées par URL + headers, (2) le cache applicatif (Redis) stocke des fragments/objets internes (config, layout, blocks) consommés par Magento, (3) l’index de recherche (Elasticsearch) est un moteur de requêtes full-text et d’agrégations, pas un simple « LIKE » accéléré. Comme le résume la doc Varnish : « Varnish Cache is a web application accelerator also known as a caching HTTP reverse proxy » (Varnish Software, varnish-cache.org). Le cache HTTP, c’est l’arme principale pour la latence et le CPU — le reste sert à ne pas saboter ce gain.

Ajoutez une nuance de « terrain » : la géolocalisation n’est pas un gadget. Si votre clientèle est majoritairement en France/Belgique/Suisse, placez Nginx/Varnish au plus près de la zone (ex. région cloud Paris) et évitez les allers-retours transfrontaliers entre frontend et backend (RTT qui s’additionnent sur chaque miss). À l’inverse, si vous avez un trafic international, une stratégie CDN + Varnish « origin » est souvent plus rentable qu’un unique point d’entrée.

Enfin, gardez en tête que Magento est très sensible à la segmentation store / devise / groupe client : vos clés de cache HTTP (Vary, cookies, headers Magento) doivent refléter ce qui change réellement. Une erreur classique est de laisser passer un cookie de tracking qui fait varier toutes les pages et annihile le cache.

Nginx + PHP-FPM : réduire le coût de chaque miss (et éviter les faux goulots)

Même avec un Varnish performant, vous aurez des miss (utilisateurs loggés, pages non cachables, invalidations, bots). Nginx doit donc être configuré comme un frontal stable, avec un upstream PHP-FPM dimensionné, et surtout des timeouts cohérents pour éviter des files d’attente invisibles. Si vous avez besoin de remettre à plat le flux Nginx → PHP-FPM (buffers, fastcgi params, statuts), vous avez un rappel utile ici : PHP-FPM : comprendre le flux d’exécution avec Nginx et Apache. Le symptôme classique d’une mauvaise config n’est pas « ça rame », c’est p95 qui explose quand le trafic augmente, car la saturation se fait sur les sockets, pas sur le CPU.

Côté Nginx, ciblez d’abord la stabilité : worker_processes auto;, worker_connections réalistes, keepalive_requests élevé, et des logs exploitables (latence upstream, cache status). Exemple minimal de format de log utile en prod :

log_format perf '$remote_addr - $request $status '
                'rt=$request_time urt=$upstream_response_time '
                'uaddr=$upstream_addr bytes=$bytes_sent '
                'ref="$http_referer" ua="$http_user_agent"';
access_log /var/log/nginx/access.log perf;

Avec ça, vous corrélez immédiatement la latence côté Nginx (rt) et côté backend (urt). Et surtout, servez le statique sans PHP (images, CSS, JS, media) avec try_files + cache headers, sinon vous gaspillez le bénéfice de Varnish.

Quelques optimisations « propres » qui coûtent peu et évitent des faux goulots :

  • Limiter le travail par requête : désactiver l’accès disque inutile (sendfile on;, tcp_nopush on; selon contexte), activer un cache de métadonnées (open_file_cache) si votre filesystem est sollicité.
  • Timeouts cohérents : un proxy_read_timeout trop haut masque les backends lents (vous « tenez » des connexions), trop bas crée des 504 en chaîne.
  • Compression : gzip/brotli peut aider sur HTML/CSS/JS, mais surveillez le CPU si votre hit ratio Varnish est faible (compresser du contenu généré dynamiquement coûte plus cher).
  • Logs actionnables : ajoutez un request_id (ou propagez celui du load balancer) pour tracer une requête de bout en bout dans Nginx, Varnish et PHP.

Côté PHP-FPM, l’objectif n’est pas « beaucoup de workers », c’est le bon nombre pour que chaque process ait de la RAM (OPcache + code + runtime) et que le CPU ne thrash pas. En 2026, sur Magento, un pm = dynamic est souvent plus tolérant en charge variable, mais en charge stable le pm = static est plus prédictible (au prix d’une sur-allocation). Le réglage OPcache est non négociable : si vous ne l’avez pas calibré, vous faites du « compile à la demande » sous charge. Référez-vous à : PHP OPcache : paramètres recommandés pour optimiser les performances.

Un mini-calcul simple (souvent oublié) pour éviter le surdimensionnement « aveugle » :

  • Mesurez la RAM moyenne d’un worker PHP-FPM en charge (ex. via ps, smem ou métriques).
  • Gardez une marge pour l’OS + Nginx + buffers + pics.
  • pm.max_children ≈ (RAM_disponible_pour_PHP) / (RAM_moyenne_par_worker)

Exemple réaliste : si vous avez 16 Go RAM, que vous réservez ~4 Go au reste (OS + Nginx + Varnish local éventuel), il reste 12 Go. Si un worker Magento consomme ~250–350 Mo en charge, viser 30–40 workers peut être cohérent. Au-delà, vous « gagnez » rarement du débit : vous gagnez surtout du context switch et des files d’attente plus opaques.

Deux réglages de diagnostic qui vous font gagner du temps en incident :

  • pm.status_path (pour voir idle/active, queue, etc.)
  • request_slowlog_timeout + slowlog (pour capturer les scripts qui dépassent un seuil)

Varnish : mettre Magento en cache sans casser le panier (ni l’indexation)

Varnish apporte le gros des gains TTFB et CPU, mais uniquement si (1) le cache est correctement segmenté (vary, cookies), (2) l’invalidation est maîtrisée, (3) le trafic anonyme est majoritaire sur les pages lourdes. Sur un e-commerce « catalogue-first », une cible réaliste est d’obtenir un cache hit ratio > 80% sur les pages catégories/produits en heures pleines. Un cas typique : passer de 40–60 ms de TTFB (hit Varnish) vs 400–900 ms (miss PHP) sur le même endpoint HTML. Le résultat immédiat : moins de workers PHP, moins d’I/O MySQL, et une latence plus stable (p95 qui se rapproche du p50).

Magento fournit une VCL générée (selon la version) et des recommandations côté headers. Votre problème n’est pas d’écrire une VCL « intelligente », c’est d’éviter les pièges : cookies de tracking qui rendent tout non cachable, pages qui changent selon l’utilisateur mais sans Vary explicite, et purge mal cadrée qui fait « tomber » le hit ratio après chaque déploiement. Le réglage grace (servir du contenu légèrement expiré pendant que le backend recalcule) est l’une des optimisations les plus rentables, surtout pendant les pics : vous préférez livrer un HTML à J+30s plutôt que de faire timeout sur PHP-FPM.

Un point très concret sur Magento : le « panier » et les infos personnalisées ne doivent pas vous forcer à désactiver le cache HTML global. La pratique courante est :

  • HTML catalogue cachable (public)
  • contenu privé (ex. mini-cart, wishlist, état connecté) chargé via requêtes dédiées / endpoints « privés » non cachés ou cachés côté navigateur selon la stratégie Magento

Pour valider rapidement votre stratégie de cache sans instrumentation complexe, faites des contrôles simples :

  • curl -I https://votresite/... (vérifiez Cache-Control, Age, et un header de diagnostic X-Cache: HIT/MISS si vous l’ajoutez)
  • vérifiez que les cookies de tracking ne « polluent » pas le cache sur les pages publiques (un cookie = une variation potentielle)
  • comparez TTFB hit vs miss sur une même URL (avant/après purge)

L’invalidation est le point qui fait dérailler les stacks. Deux stratégies existent : purge par URL (simple, mais peut être volumineux) et ban/purge par tags (plus propre, mais dépendant de l’implémentation). Magento utilise des tags de cache (type X-Magento-Tags) pour invalidation fine ; vérifiez qu’ils ne sont pas supprimés/écrasés par Nginx. Exemple d’opération safe en exploitation (via varnishadm) :

# Purge une URL exacte (prudence : impact cache)
varnishadm 'ban req.url == "/men/tops-men/jackets-men.html"'

# Vérifier l’état
varnishadm ban.list

Un piège courant en production : purger trop large lors d’un import catalogue ou d’un déploiement. Mini-schéma de « blast radius » à éviter :

  • déploiement → purge totale → reindex → Varnish cold → pics de miss → PHP-FPM saturé → DB saturée → timeouts → retry bots → spirale.

À l’inverse, une approche plus robuste :

  • purges ciblées (URLs/Tags) + grace + préchauffage (warm-up) des URL les plus vues
  • indexation planifiée hors pics
  • limitation (rate limit) des bots agressifs sur les endpoints non cachables

Pour l’aspect « documentation officielle » (utile quand vous standardisez vos pratiques en équipe), la configuration Varnish est également décrite côté Adobe Commerce : experienceleague.adobe.com — Configuration Varnish

Enfin, ne sacrifiez pas l’indexation : les bots doivent voir un HTML cohérent et rapide. Les corrélations Core Web Vitals / crawl budget ne sont pas théoriques sur gros catalogues. Pour cadrer l’impact SEO côté perf (même si l’exemple est PrestaShop, les métriques sont identiques), gardez sous la main : SEO PrestaShop : checklist technique 2025 pour indexation et performance.

Redis : sessions et cache applicatif Magento sans transformer Redis en point unique de panne

Redis est souvent présenté comme « juste un cache », mais sur Magento il devient rapidement un composant critique : sessions, cache backend, verrous, parfois file d’attente selon l’architecture. La phrase la plus citée de la doc est utile parce qu’elle rappelle l’ambiguïté fonctionnelle : « Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker » (Redis, redis.io). En e-commerce, cette polyvalence se paye : si vous mélangez tout dans une seule instance sans quotas, une montée en charge sur les sessions peut évincer des clés de cache, puis forcer Magento à recalculer, puis faire exploser PHP et MySQL.

Le pattern robuste : séparer (au minimum) sessions et cache (instances dédiées ou bases/logical DB distinctes + limites mémoire). Pour les sessions, privilégiez une politique d’éviction qui respecte le TTL (ex. volatile-lru ou volatile-ttl) et fixez maxmemory pour éviter que Linux ne swap. Pour le cache applicatif, allkeys-lfu (ou allkeys-lru) peut faire sens si vous avez un grand volume de clés non TTL. Dans tous les cas, l’échec « silencieux » est plus dangereux que la panne franche : activez des timeouts côté client, et surveillez evicted_keys, used_memory_peak, connected_clients, instantaneous_ops_per_sec.

Quelques choix d’architecture qui évitent que Redis devienne « le SPOF » (single point of failure) de votre performance Magento :

  • Réseau : Redis doit être proche de PHP-FPM (même LAN/VPC). Une latence réseau de quelques millisecondes répétée des milliers de fois par page se voit immédiatement sur le p95.
  • Haute disponibilité : si Redis porte les sessions, prévoyez au minimum réplication + mécanisme de bascule (ex. Sentinel côté Redis, ou service managé). Sans ça, une panne Redis = pertes de session = checkout dégradé.
  • Sécurité : évitez l’exposition réseau, utilisez des ACL/mots de passe, et n’ouvrez pas Redis sur Internet (c’est une cause classique d’incidents). Si vous devez traverser des segments réseau, chiffrement/TLS via un proxy ou offre managée.
  • Backups : pour une instance « cache », la persistance est souvent inutile ; pour des sessions, la persistance n’est pas un vrai plan de continuité (les sessions ont un TTL), mais peut aider à réduire l’impact d’un redémarrage selon votre contexte.

Côté Linux, deux points sont souvent oubliés : vm.overcommit_memory=1 (recommandé par Redis pour éviter des échecs d’allocation) et net.core.somaxconn (file d’attente). Côté Magento, ne « bricolez » pas : utilisez la configuration supportée via app/etc/env.php (ou équivalent), et documentez vos choix en runbook (politique d’éviction, persistance RDB/AOF, sauvegarde). La persistance AOF sur une instance session est rarement utile et peut ajouter de la latence disque ; en revanche sur une instance cache, la persistance n’apporte souvent rien (un cache est reconstructible) et peut être supprimée pour réduire l’I/O.

Un mini-check de prod (très concret) quand « ça ralentit » et que Redis est suspect :

  • evicted_keys augmente : votre maxmemory est trop bas ou votre politique d’éviction est inadaptée.
  • connected_clients explose : fuite de connexions ou pool mal géré côté PHP.
  • latence Redis en hausse mais CPU bas : souvent saturation réseau, ou I/O disque dû à une persistance mal configurée.
  • used_memory_peak proche de maxmemory en continu : votre working set ne tient pas en RAM, vous êtes en mode « cache instable ».

Elasticsearch (ou OpenSearch) : latence de recherche, indexation, et dérives de ressources

Depuis Magento 2.4, la recherche catalogue repose sur Elasticsearch/OpenSearch, donc votre « performance Magento » inclut la performance du cluster search. Elasticsearch se définit comme « a distributed, RESTful search and analytics engine » (Elastic, elastic.co). Concrètement : c’est un JVM service qui consomme RAM/CPU, et qui devient instable si vous le traitez comme un binaire « secondaire ». Sur une boutique à 100k–500k produits, une indexation complète + requêtes facettées + autosuggest peuvent suffire à saturer un nœud mal dimensionné.

Les basiques qui évitent 80% des problèmes : heap JVM à ~50% de la RAM du nœud (sans dépasser ~32 Go pour garder les compressed oops), disque rapide (NVMe si possible), et un nombre de shards raisonnable (trop de shards = overhead). Les requêtes Magento sont souvent riches en agrégations (facettes) ; la latence dépend donc autant du mapping (types, analyzers, normalizers) que du hardware. Ajoutez des synonymes et du stemming avec prudence : chaque sophistication d’analyse a un coût d’indexation et parfois de pertinence. Pour cadrer les choix (ES vs alternatives, coût de pertinence), vous pouvez croiser avec : Moteur de recherche marketplace : Meilisearch, Elasticsearch ou Algolia.

Deux mini-situations typiques (et comment les éviter) :

  • Filtres/facettes « qui tuent » : une catégorie avec beaucoup d’attributs filtrables + tri + facettes multi-sélections peut générer des agrégations coûteuses. Réduisez les attributs filtrables non essentiels, et vérifiez que vos champs sont correctement typés (keyword vs text).
  • Reindex en pleine charge : un reindex complet augmente CPU/IO + pression sur le heap. Planifiez hors pics, et évitez les opérations de maintenance au moment où la recherche est la plus utilisée (soirées, opérations promo).

Le piège opérationnel : indexers Magento + cluster search qui se dégrade sous charge. Si vos indexers tournent en même temps que vos pics de trafic, vous ajoutez une charge CPU/IO précisément quand vous cherchez de la stabilité. Décalez les reindex complets, privilégiez l’incrémental, et instrumentez les temps de réponse côté moteur (p95 sur endpoints search). Et n’oubliez pas que MySQL reste une dépendance : des requêtes lentes côté DB peuvent faire « croire » à un problème Elasticsearch alors que la latence vient de la génération des filtres/collections. Les méthodes d’analyse (slow query log, index) restent pertinentes, même hors PrestaShop : PrestaShop MySQL : analyser slow query log et optimiser index.

Dernier point « infra » très concret : placez Elasticsearch/OpenSearch dans la même zone réseau que Magento (même région, idéalement même datacenter/VPC). Un moteur de recherche éloigné (cross-region) peut rester « stable » mais ajouter une latence incompressible sur toutes les pages qui appellent la recherche (y compris certaines pages catégories selon implémentation).

Dimensionnement, observabilité et rollout : prouver le gain (et éviter l’usine à gaz)

Avant d’empiler des briques, dimensionnez en fonction d’un objectif mesurable : p95 < 300 ms sur pages catalogue (hit), p95 < 1.5 s sur pages dynamiques critiques, et un hit ratio Varnish stabilisé (ex. > 80% sur catalogue). En infra, la vraie question devient « où mettre la RAM » : Redis et Elasticsearch en consomment, PHP-FPM aussi (OPcache + workers). Si vous hésitez entre mutualisé, VPS, dédié, cloud managé, reprenez une grille de choix « infra-first » (même si elle parle PrestaShop, le raisonnement est identique) : Hébergement PrestaShop : mutualisé, VPS ou cloud managé, comment choisir.

Un repère simple de dimensionnement (à adapter à votre trafic et catalogue) : si vous n’avez pas la RAM pour Redis + heap JVM + OPcache + buffers, vous aurez une stack « théoriquement moderne » mais instable. Souvent, mieux vaut :

  • un Varnish efficace + PHP-FPM correctement réglé + MySQL optimisé
  • puis ajouter Redis (bien isolé)
  • puis industrialiser Elasticsearch/OpenSearch (ou le managé) plutôt que tout empiler sans marge mémoire.

L’observabilité doit couvrir les 4 couches : (1) Nginx (requesttime, upstreamtime, erreurs 4xx/5xx), (2) Varnish (hit/miss, backend busy, bans), (3) Redis (latence, evictions, memory), (4) Elasticsearch (heap, GC, query latency), plus PHP-FPM et MySQL. Pour du monitoring rapide, Netdata est efficace sur les métriques « systèmes + services » : Netdata : activer et configurer les collectors pour monitoring temps réel. Pour une approche SRE (alerting, PromQL, budgets d’erreur), structurez ensuite avec : Prometheus : configuration des alertes, métriques et requêtes PromQL.

Un tableau de diagnostic rapide (utile en runbook) quand « la performance Magento » se dégrade :

Symptôme Suspect fréquent Où regarder en premier
p95 monte, CPU faible file d’attente / saturation connexions Nginx urt, PHP-FPM queue, timeouts
Varnish hit ratio chute cookies/headers, purge trop large logs Varnish, cookies, ban.list
timeouts intermittents backend instable / GC / IO Elasticsearch heap/GC, Redis latence, MySQL slow log
checkout dégradé sessions/locks Redis sessions, saturation réseau, erreurs PHP

Enfin, le rollout. Sur Magento, un déploiement qui purge tout le cache et relance des indexers en plein trafic est la recette du crash « post-release ». Travaillez en pré-production, testez au k6/wrk avec un jeu d’URLs représentatif (catalogue + search + cart), et adoptez une stratégie qui limite le blast radius (blue/green ou canary). Un détail qui change tout en prod : prévoir un pré-chauffage (warm-up) des pages catalogue clés après purge/déploiement, pour éviter que vos vrais utilisateurs essuient les miss.

Si vous manipulez des ACL Nginx/Varnish/WAF, gardez un runbook de diagnostic des erreurs d’accès : les 403 en chaîne sont fréquents lors de l’ajout de reverse proxies ou de règles de purge. Méthodo utile : Erreur 403 Forbidden : causes et dépannage étape par étape. La stack Nginx + Varnish + Redis + Elasticsearch n’est pas « magique » : elle marche quand vous pouvez mesurer, segmenter et industrialiser — sinon, elle ne fait que déplacer la complexité.


À lire aussi