Table des matières :
- Dimensionner un pic TV : transformer une audience en charge serveur mesurable
- Stabiliser le front de la boutique : CDN/WAF, Nginx, PHP-FPM, OPcache
- Cache applicatif PrestaShop : ce qui marche, ce qui casse, et comment l’échauffer
- MySQL/MariaDB : le goulot réel pendant un passage TV
- Sécuriser le checkout : dégrader intelligemment sans tuer la conversion
- Observabilité et runbook jour J : éviter la panne « silencieuse »
Dimensionner un pic TV : transformer une audience en charge serveur mesurable
Prérequis de base avant de toucher à la prod : PrestaShop 8.1+ ou 9.x, PHP 8.2/8.3 (idéalement FPM), accès SSH, accès MySQL avec droits de lecture sur performance_schema, et un environnement de staging cloné (DB + fichiers) pour exécuter des tests destructifs. Si vous êtes encore sur un mutualisé sans accès aux métriques (status FPM, slow logs, etc.), la préparation d’un passage TV se résume souvent à « prier », et ce n’est pas une stratégie d’ingénierie.
La première étape consiste à convertir le passage TV en hypothèses chiffrées : audience × taux de scan/visite × répartition temporelle. Exemple réaliste : 800 000 téléspectateurs, 0,4% qui tapent l’URL ou scannent un QR code dans les 10 minutes → 3 200 sessions en 10 minutes. Avec 3 pages vues/session, ça fait 9 600 pages vues/10 min ≈ 16 RPS (requêtes HTTP/s) sur les pages HTML, sans compter les assets (JS/CSS/images) si vous n’avez pas de CDN. Sur un thème lourd, le HTML peut déclencher 40–120 requêtes SQL par page : la base devient votre goulot avant le CPU.
Pour éviter les erreurs de dimensionnement les plus fréquentes, ajoutez deux paramètres dans vos hypothèses :
- La durée moyenne d’une session (ou au moins la durée moyenne entre 2 pages) : un pic TV, ce n’est pas seulement du volume, c’est de la concurrence.
Approximation utile:concurrence ≈ RPS × temps_moyen_de_traitement(en secondes)
Exemple : 16 RPS avec 800 ms de temps serveur moyen ⇒ ~13 requêtes simultanées côté PHP, auxquelles s’ajoutent les pics (p95/p99) et les assets. - Le ratio “pages dynamiques” vs “pages quasi-statiques” : une fiche produit non loguée n’a pas le même coût qu’un panier (écritures, recalculs, règles panier).
Une manière simple de poser les hypothèses (et d’aligner marketing/tech) est de remplir un mini-tableau avant tout test :
| Paramètre | Hypothèse | Comment la valider vite |
|---|---|---|
| Audience exposée | 800 000 | estimation régie / planning TV |
| Taux de visite | 0,2–1,0% | historique campagnes + hypothèse QR |
| Fenêtre de trafic | 5–15 min | format spot + rappel animateur |
| Pages / session | 2–4 | analytics existants |
| Part checkout | 1–5% | taux d’ajout panier / conversion |
| RPS cible HTML | calcul | convertir en objectifs de test |
Ensuite, vous mesurez votre coût par page et le point de rupture, pas celui d’un autre. Utilisez k6 (ou Gatling/JMeter) pour viser des métriques exploitables : latence p95/p99, taux d’erreurs, saturation FPM (busy workers), Threads_running côté MySQL. Un test utile isole 3 scénarios : (1) landing catégorie/produit en visiteur non logué, (2) ajout panier, (3) checkout jusqu’au paiement (sans débiter). Si vous n’avez pas de méthode, partez de l’article interne « Audit performance PrestaShop : méthode reproductible et preuves terrain » et adaptez le protocole au trafic TV (plus court, plus brutal).
Deux précautions rendent vos tests réellement prédictifs :
- Reproduire les mêmes headers/cookies qu’un vrai navigateur (compression, HTTP/2, cache headers), sinon vous sur/sous-estimez la charge.
- Tester “cache froid” puis “cache chaud” : le pic TV commence presque toujours par un moment où OPcache/Smarty/Redis ne sont pas “chauffés”, et c’est souvent là que la boutique tombe.
Pour démarrer sans “réinventer la roue”, la documentation k6 (scénarios, ramping, thresholds) est ici.
Stabiliser le front de la boutique : CDN/WAF, Nginx, PHP-FPM, OPcache
Avant de scaler PHP, retirez le maximum de charge au couple PHP/MySQL. Un passage TV génère un ratio assets/HTML énorme (images produit, JS du thème, webfonts). Sans CDN, vous consommez des sockets, de la bande passante et des I/O disque pour servir des fichiers statiques… alors que c’est le job naturel d’un CDN. Mettez au minimum vos chemins statiques derrière un CDN (Cloudflare, Fastly, etc.) et forcez des cache-control longs avec versioning (hash). Pour le choix et les implications, voir « CDN : comparatif Cloudflare, Fastly, Akamai, CloudFront, Bunny.net, KeyCDN ».
Concrètement, l’objectif “jour J” côté front est souvent :
- HTML : stable (pas forcément ultra-rapide), sans pics erratiques de TTFB
- Assets : servis majoritairement par le CDN (hit ratio élevé), avec des TTL longs
- Images : tailles adaptées (éviter d’envoyer des 2000px si le thème affiche 600px)
Une erreur courante : “j’ai un CDN” mais les images sont non-cacheables (headers absents), ou bien l’URL ne change jamais alors que l’image change (pas de versioning) ⇒ le CDN revalide sans cesse et vous perdez l’intérêt du cache.
Côté edge, préparez la partie sécurité et anti-bot. Les pics TV attirent aussi du scraping opportuniste et des scans. Activez un WAF et surtout une règle de rate limiting sur les endpoints sensibles (login, recherche, facettes, cart, order, endpoints Ajax). Nginx fournit limit_req et limit_conn (voir la documentation nginx sur limit_req), et Cloudflare a des Rate Limiting Rules. Le point clé : vous protégez la base et PHP contre les requêtes coûteuses, même si ça « dégrade » l’expérience de 1% des clients.
Un pattern simple et efficace consiste à limiter plus fort ce qui est coûteux et facile à abuser (recherche, facettes) que ce qui convertit (fiche produit, panier). Exemple (à adapter, et à tester en staging) :
# Exemple : limiter la recherche (souvent très coûteuse)
limit_req_zone $binary_remote_addr zone=search_zone:10m rate=2r/s;
location /recherche {
limit_req zone=search_zone burst=10 nodelay;
proxy_pass http://php_upstream;
}
# Exemple : réduire l'impact des bursts de checkout
limit_req_zone $binary_remote_addr zone=checkout_zone:10m rate=1r/s;
location ~ ^/(commande|order) {
limit_req zone=checkout_zone burst=5;
proxy_pass http://php_upstream;
}
Pour comprendre les symptômes côté HTTP, gardez en tête la définition normative : « The 503 (Service Unavailable) status code indicates that the server is currently unable to handle the request due to a temporary overload or scheduled maintenance. » (RFC 7231, section 6.6.4 : RFC 7231).
Sur l’origin, verrouillez PHP-FPM/OPcache. OPcache doit être activé, dimensionné (opcache.memory_consumption, opcache.max_accelerated_files) et surtout stable (pas de revalidation agressive en prod). PHP-FPM doit exposer un status (pm.status_path) pour observer active processes, max children reached. Ajustez pm.max_children en fonction de la RAM disponible et de la mémoire réelle par process (mesurée via ps -o rss). Gardez une marge : un pic TV peut déclencher des chemins de code plus lourds (génération d’images, modules marketing, règles panier), donc la mémoire/process augmente.
Checklist rapide “front stable” (souvent négligée) :
- keep-alive correctement configuré (éviter de multiplier les handshakes)
- timeouts cohérents (ne pas garder des workers bloqués 60s sur un appel externe)
- pages d’erreur 50x cacheables côté CDN (au moins quelques secondes) pour éviter l’effet “retry storm” côté clients
Si vous migrez ou durcissez la stack Nginx/PHP/Redis/Cloudflare, l’article « Hébergement WordPress géré : Nginx PHP 8.4 Redis et Cloudflare » reste pertinent sur les patterns infra (même si l’applicatif n’est pas WordPress).
Cache applicatif PrestaShop : ce qui marche, ce qui casse, et comment l’échauffer
Le cœur de PrestaShop n’est pas conçu pour absorber des pointes brutales sans stratégie de cache. Le cache Smarty (templates compilés) et la configuration en mémoire aident, mais le vrai gain vient du découplage : (1) assets via CDN, (2) cache d’objets/queries via Redis, (3) OPcache côté PHP. En PrestaShop 8/9, Redis est souvent utilisé via modules ou configuration avancée (selon distribution/hébergeur). Le piège classique : activer Redis sans comprendre la granularité d’invalidation → incohérences de prix/stock en plein pic.
Pour éviter les fausses bonnes idées, retenez ceci : micro-cacher du HTML complet est risqué à cause des cookies (panier, devise, langues, groupe client, taxes). Varnish/fastcgi_cache peuvent fonctionner mais exigent une stratégie de variation (cookies, headers) et une liste d’URLs safe (pages purement publiques). Sur une boutique TV, la tactique la moins dangereuse reste : zéro cache HTML (sauf landing statique dédiée), mais cache agressif des assets + réduction drastique des hits DB. Pour une vue d’ensemble des erreurs fréquentes (multiboutique, invalidations, conflits), voir « Cache PrestaShop : erreurs fréquentes et bonnes pratiques multiboutique » et « Cache PrestaShop : stratégie 2026 OPcache, Redis, Varnish et CDN ».
Un compromis très “TV-friendly” (souvent sous-estimé) : créer une landing dédiée (URL simple, peu de modules, peu de blocs dynamiques) qui renvoie vers une catégorie ou un produit. Vous réduisez :
- le nombre de modules exécutés
- la profondeur de navigation (moins de requêtes “annexes”)
- le risque de cache “sale” (moins de variations utilisateur)
L’échauffement (« warming ») est souvent oublié : un pic TV arrive d’un coup, donc caches froids = CPU/DB en feu. Faites tourner un robot interne (k6 en mode low-RPS, ou un script curl) qui visite les top URLs (home, catégories, best sellers, 20 fiches produit) 30 minutes avant l’antenne, et continue pendant la fenêtre TV. Objectif : remplir OPcache, compiler Smarty, remplir les caches applicatifs, et surtout charger les pages qui déclenchent la génération d’images/miniatures (à pré-générer si possible).
Mini-checklist de warming “utile” (pas juste symbolique) :
- visiter la landing TV + la catégorie ciblée + les 10 produits mis en avant
- forcer le chargement des variantes (déclenche parfois des requêtes spécifiques)
- vérifier que les miniatures sont déjà générées (sinon, régénérez en amont)
- exécuter le warming avec un user-agent identifiable et whitelisté au WAF/CDN (sinon vous warmerez… à moitié)
Si votre boutique est lente au TTFB ou souffre de bots, la checklist « PrestaShop lent : diagnostic TTFB, bots et optimisation serveur » aide à traiter les causes structurelles avant de « surdimensionner » à l’aveugle.
MySQL/MariaDB : le goulot réel pendant un passage TV
Sur PrestaShop, MySQL est souvent la première limite : facettes, règles panier, prix spécifiques, stock, et recherche « native » génèrent des requêtes lourdes et répétitives. Le passage TV est un amplificateur : un même produit/catégorie est consulté par des milliers de personnes en quelques minutes, donc les mêmes requêtes se répètent. Si vous n’avez pas de monitoring SQL, vous pilotez au ressenti. Activez le slow query log (en staging d’abord, puis en prod avec seuil raisonnable) et observez les temps cumulés, pas juste les « plus lentes ».
Très concrètement, pour prioriser, vous voulez identifier :
- les requêtes les plus fréquentes
- les requêtes au temps total le plus élevé (fréquence × durée)
- les requêtes qui déclenchent
filesort/temporary table - les requêtes qui font exploser
Rows_examined(beaucoup de lignes lues pour peu de lignes retournées)
Avec performance_schema, une requête de diagnostic (lecture seule) utile en staging/prod pour trouver les digests dominants ressemble à ceci :
SELECT
DIGEST_TEXT,
COUNT_STAR AS exec_count,
ROUND(SUM_TIMER_WAIT/1e12, 2) AS total_s,
ROUND(AVG_TIMER_WAIT/1e12, 4) AS avg_s
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
Ce n’est pas “magique”, mais ça évite de perdre du temps sur la requête la plus lente si elle ne s’exécute que 3 fois, alors qu’une requête “moyenne” s’exécute 200 000 fois pendant le pic.
Au niveau optimisation, l’ordre rationnel est : (1) identifier les requêtes dominantes (top total time), (2) vérifier les index avec EXPLAIN, (3) corriger les index et/ou le code, (4) seulement ensuite toucher à la configuration. L’article « Index MySQL : composer, mesurer avec EXPLAIN et optimiser les requêtes » donne une méthode, et « Audit MySQL/MariaDB : optimiser les requêtes lentes e‑commerce » complète sur l’interprétation terrain (cardinalité, filesorts, temporary tables). Sur PrestaShop, les tables problématiques récurrentes sont ps_specific_price, ps_cart_rule, ps_product_attribute, ps_stock_available, ps_feature_product et les tables de facettes.
Deux leviers “rapides” (souvent rentables avant de toucher au code) :
- S’assurer que l’InnoDB buffer pool est correctement dimensionné : si
Innodb_buffer_pool_readsgrimpe vite pendant un test, vous lisez trop souvent sur disque (ou vous invalidez trop). - Réduire le coût de la recherche/facettes pendant la fenêtre TV : ce sont des features utiles, mais ce sont aussi des multiplicateurs de requêtes sur le catalogue quand tout le monde arrive en même temps.
Enfin, ne sous-estimez pas les gains d’architecture. Si vous avez le temps et la maturité ops : réplique de lecture (read replica) pour déporter certaines lectures (mais PrestaShop n’est pas nativement multi-DB, donc il faut un proxy SQL, du split applicatif ou un hébergeur qui l’abstrait). Alternative plus simple : basculer la recherche vers un moteur dédié pour ne plus marteler MySQL (Elasticsearch/OpenSearch/Meilisearch). C’est particulièrement utile quand ps_searchbar + recherche MySQL sature CPU/DB. Voir « Elasticsearch PrestaShop : accélérer la recherche et les facettes catalogue ».
Sécuriser le checkout : dégrader intelligemment sans tuer la conversion
Le trafic TV n’a pas seulement un problème de pages vues : il pousse aussi le tunnel de commande (création compte, adresses, transporteurs, paiement) et donc les écritures SQL, les locks et les dépendances externes. Le cœur PrestaShop est majoritairement synchrone : si un transporteur, un PSP ou un module fait un appel réseau lent (API shipping, anti-fraude, ERP), votre worker PHP reste bloqué. Résultat : saturation FPM, file d’attente, puis 502/504/503. C’est là que vous devez être brutal : pendant la fenêtre TV, désactivez toute fonctionnalité non critique du checkout (reco produit, chat, tracking lourd, calculs marketing), ou mettez-les derrière un feature flag.
Un moyen pragmatique de décider “quoi couper” est de classer chaque brique par impact conversion vs coût technique :
| Brique | Valeur business | Risque sous pic | Action TV typique |
|---|---|---|---|
| Paiement | critique | dépendance externe | sécuriser timeouts + fallback |
| Transporteurs | critique | API lente / calculs | simplifier options, caches |
| Reco/upsell | moyenne | requêtes + JS | désactiver temporairement |
| Chat / widgets | faible à moyenne | scripts tiers | couper |
| Tracking avancé | moyenne | scripts + latence | mode “léger” |
La dépendance paiement est la plus sensible. Vérifiez les timeouts du module, la stratégie de retry, et la validation des webhooks. Si vous subissez des bursts côté webhooks, appliquez des quotas et des backoffs, sinon vous DDoS votre propre back-office. Les règles de base sur les quotas et les réponses 429 sont détaillées dans « API Rate Limits : comprendre les quotas, headers de limite et erreurs 429 ». Si vous utilisez PayPal et consommez des webhooks, gardez une validation stricte (signature, idempotence) : « Webhooks PayPal : vérifier l’authenticité des notifications serveur ».
Sur l’idempotence, soyez concret : pendant un pic, les clients refreshent, les mobiles changent de réseau, certains PSP renvoient des callbacks en double. Si vous n’avez pas de garde-fou, vous créez :
- doubles commandes
- doubles tentatives de capture
- exports ERP en doublon
Sur la partie stock/commande, cherchez les sections critiques et rendez-les idempotentes. Exemple : si votre module export ERP envoie la commande en synchrone lors du hookActionValidateOrder, vous avez une bombe sous le pic : ERP lent = commandes bloquées = clients qui refresh = doublons. La solution saine : mettre en file (queue) et ack côté front, puis traiter en asynchrone (worker). Même sans refonte complète, vous pouvez (a) écrire une table de queue, (b) pousser un message via Redis Streams/RabbitMQ, (c) exécuter un cron/worker isolé. Pour les architectures de sync bidirectionnelle et les échecs, voir « Intégration API : synchronisation bidirectionnelle et automatisation pour forte volumétrie ».
Observabilité et runbook jour J : éviter la panne « silencieuse »
Le jour du passage TV, vous n’avez pas le temps « d’analyser ». Vous devez voir en 30 secondes si c’est PHP, MySQL, réseau, CDN, ou un module. Mettez un dashboard minimal : RPS, taux d’erreurs (4xx/5xx), latence p95, saturation FPM (max children reached), Threads_running, Innodb_buffer_pool_reads, et taux de cache hit CDN. Si vous n’avez pas de stack de monitoring, Netdata est un compromis rapide (agent + dashboards) : « Netdata : intégrer Prometheus, SNMP et StatsD pour tout surveiller ».
Pour rendre le dashboard actionnable, associez un seuil → une action. Exemple de règles simples (à calibrer sur vos tests) :
- p95 > 2s et FPM “max children reached” > 0 → réduire la pression : limiter recherche/facettes, couper modules non critiques
Threads_runninggrimpe et slow log explose → geler les features SQL-heavy (recherche, filtres), vérifier index / plan de requête dominant- taux 5xx augmente mais CDN hit ratio bon → suspecter origin (PHP/DB), pas l’edge
Préparez un runbook « dégradation contrôlée » avec des actions réversibles et ordonnées : 1) bloquer/limiter la recherche et les facettes, 2) désactiver modules non critiques, 3) activer une page d’attente pour les routes checkout si le PSP est KO, 4) basculer temporairement vers une landing statique CDN (qui renvoie vers une URL de commande différée), 5) si besoin, maintenance mode ciblée. Les erreurs 503 ne se diagnostiquent pas au hasard : gardez sous la main une procédure logs PHP/Nginx/Apache/LiteSpeed selon votre stack, par exemple « Erreur HTTP 503 : diagnostiquer PHP et logs Apache/LiteSpeed ».
Ajoutez aussi une discipline “change management” spécifique TV (souvent la cause racine des incidents) :
- gel des déploiements 24–48h avant (hors correctifs validés)
- un seul “owner” des changements infra pendant la fenêtre TV
- une fenêtre de rollback documentée (quoi, comment, en combien de minutes)
Enfin, assumez l’angle SRE : on ne « promet » pas l’absence d’incident, on prépare la détection et le rétablissement. La citation canonique résume bien l’approche : « Site Reliability Engineering is what happens when you ask a software engineer to design an operations team. » (Betsy Beyer et al., Site Reliability Engineering, O’Reilly, 2016). Concrètement : (a) un canal incident unique, (b) un responsable de décision (pas 5 personnes qui changent des réglages), (c) un plan de rollback (release gelée 24–48h avant), et (d) une check-list post-pic (purge caches maîtrisée, vérif commandes, rattrapage des jobs async).
Après le passage TV, ne “rangez” pas tout trop vite : comparez vos hypothèses aux métriques (RPS réel, p95, erreurs, requêtes SQL dominantes). C’est votre meilleure matière pour le prochain prime. Si votre boutique a été modernisée avec déploiements automatisés, vous avez un vrai levier de rollback : « PrestaShop : modernisation et reprise de boutique avec déploiements automatisés ».




