Rien ne fait chuter la conversion plus vite qu’un panier qui oublie son existence. Un acheteur ajoute deux articles, appuie sur actualiser, et—pouf—panier vide. Il ne fera pas de diagnostic ; il partira. Pendant ce temps, vous regardez des tableaux de bord qui déclarent le site « sain » parce qu’un HTTP 200 n’est pas la même chose que « les gens peuvent vous payer ».
Ce problème n’est presque jamais « WooCommerce est cassé ». C’est généralement l’état qui est mangé par le cache, la portée des cookies, le stockage des sessions ou le routage multi-nœuds. La bonne nouvelle : on peut le corriger. La mauvaise : il faut être précis, parce que « vider tous les caches » n’est pas une stratégie ; c’est une confession.
Playbook de diagnostic rapide
Si vous procédez dans le bon ordre, vous trouverez le goulot d’étranglement rapidement. Si vous procédez dans le mauvais ordre, vous passerez une journée à blâmer WooCommerce et une nuit à vous blâmer.
Première étape : confirmer s’il s’agit d’une perte de cookie/session ou d’un HTML mis en cache
- Ouvrez une fenêtre en navigation privée, ajoutez un produit au panier, actualisez la page du panier et la page de paiement.
- Vérifiez les en-têtes de réponse pour des hits de cache (CDN, Varnish, Nginx FastCGI cache).
- Recherchez de nouveaux cookies après l’ajout au panier :
woocommerce_cart_hash,woocommerce_items_in_cart,wp_woocommerce_session_*.
Décision : si le HTML est mis en cache, vous avez besoin d’exclusions de cache et d’un comportement « vary » correct. Si les cookies ne persistent pas, corrigez la portée des cookies, HTTPS, SameSite, le domaine ou le stockage de session.
Deuxième étape : vérifier le routage multi-nœuds et la santé du backend de sessions
- Êtes-vous derrière un load balancer ? Y a-t-il de la persistance (stickiness) ? Le stockage des sessions WooCommerce est-il partagé (DB/Redis) entre les nœuds ?
- Utilisez-vous Redis pour l’object cache ? Supprime-t-il des clés ? maxmemory provoque-t-il des évictions ?
- La latence de la base de données augmente-t-elle ou des tables sont-elles verrouillées ?
Décision : si vous avez plusieurs nœuds web sans stockage d’objets/sessions partagé (ou mal configuré), le panier disparaîtra « au hasard » selon le nœud qui répond.
Troisième étape : valider la table de sessions WooCommerce et le comportement du cron
- WooCommerce stocke les données de session (par défaut) dans la base de données dans une table dédiée.
- Les tâches de nettoyage et le TTL comptent. Un nettoyage mal réglé peut supprimer des sessions actives.
Décision : si les sessions sont purgées ou jamais écrites, vous verrez le panier disparaître systématiquement à l’actualisation ou après un court temps d’inactivité.
Une citation pour garder l’équipe honnête (idée paraphrasée) : Eugene Rochal (cercles operations/reliability) a popularisé l’idée que la fiabilité vient de « rendre l’état explicite et observable », pas de l’espoir.
Ce qui se passe réellement quand le panier « se vide »
Le panier de WooCommerce n’est pas magique. C’est un état construit à partir de quelques ingrédients :
- Cookies côté client qui identifient la session et donnent des indices (comme le hash du panier).
- Données de session côté serveur (souvent dans
wp_woocommerce_sessionsou une table au préfixe personnalisé) indexées par l’identifiant de session. - Rendu HTML qui ne doit pas être mis en cache incorrectement, car il est spécifique à l’utilisateur.
Quand vous ajoutez un article, WooCommerce écrit ou met à jour la session, définit des cookies, puis rend le panier/mini-panier via des fragments. Le symptôme « panier qui se vide à l’actualisation » signifie généralement l’une de ces choses :
- Le navigateur n’envoie jamais le cookie de session (portée/flags du cookie incorrects).
- Le serveur ne trouve pas la session (non écrite, purgée, ou stockée ailleurs).
- Un cache renvoie la version d’une autre personne de la page (ou une version « sans panier ») parce qu’il a ignoré les cookies ou les paramètres de requête.
- Un autre nœud web gère la requête suivante et ne partage pas correctement l’état.
Il existe des variantes :
- Le panier se vide seulement sur les pages panier/checkout : règles de mise en cache ciblant ces URL, ou un plugin qui « optimise » ces chemins.
- Le panier se vide seulement après la connexion : migration de session entre invité et utilisateur connecté, incompatibilité de domaine de cookie, ou cache qui varie selon le cookie de login mais pas selon les cookies WooCommerce.
- Le panier se vide seulement sur Safari/iOS : règles de cookie plus strictes (SameSite, ITP), restrictions sur les cookies tiers, ou flux de redirection étranges.
Petite blague #1 : si votre cache sert le même panier à tout le monde, félicitations — vous avez inventé l’« expérience d’achat communautaire ». Ce n’est pas celle pour laquelle les gens paient.
Faits et contexte intéressants (ce qui explique pourquoi ça revient)
- WooCommerce s’est éloigné des sessions PHP il y a des années pour l’état du panier ; il s’appuie sur son propre système de sessions plus des cookies, car les sessions PHP sont un piège en scaling multi-nœuds.
- La mise en cache des pages WordPress est devenue courante parce que PHP+MySQL sur l’hébergement mutualisé était lent. Le e‑commerce est la charge de travail qui punit le réflexe « tout mettre en cache ».
- Varnish a popularisé la pensée « les hits de cache sont rois » dans les années 2000. Pour les paniers, le « taux de hit » est un métrique de vanité à moins d’exclure correctement les pages personnalisées.
- Les navigateurs ont durci les règles de cookies en vagues (SameSite par défaut, prévention du tracking). Beaucoup de bugs de panier sont en fait « vos flags de cookie datent de 2016 ».
- Les CDN ont commencé à mettre en cache le HTML agressivement une fois que l’edge compute l’a rendu attractif. C’est parfait pour les blogs et terrible pour le checkout à moins de traiter les cookies comme clé de cache.
- Redis est devenu l’outil de performance par défaut dans l’écosystème WordPress. Une politique d’éviction mal configurée peut supprimer des entrées d’object cache que le code suppose présentes.
- WooCommerce utilise des « cart fragments » AJAX pour que le mini‑panier se mette à jour sans rafraîchir entièrement. Si ces endpoints AJAX sont mis en cache ou bloqués, l’UI ment.
- Beaucoup de plugins « sécurité » réécrivent les en‑têtes (surtout les flags de cookies et contrôle de cache). La moitié d’entre eux vont bien ; l’autre moitié apportent le chaos via une page de réglages.
- Les load balancers ont facilité le scaling horizontal. Ils ont aussi fait de la cohérence d’état votre problème, ce qui explique pourquoi les paniers « disparaissent aléatoirement » uniquement après l’ajout du second nœud web.
Modes de défaillance : sessions, cookies, cache et stockage
1) Cookies : domaine, chemin, HTTPS, SameSite et le piège des redirections
Si le panier se vide immédiatement après actualisation, votre premier suspect est le cookie de session qui n’est pas renvoyé. Causes fréquentes :
- HTTP/HTTPS mixte : l’ajout au panier se fait en HTTPS, puis une redirection ou une canonicalisation renvoie l’utilisateur en HTTP, faisant perdre les cookies secure.
- Mauvais domaine de cookie :
example.comvswww.example.com. L’un définit des cookies que l’autre n’envoie pas. - Chemin de cookie trop strict : cookie défini pour
/shopmais le panier est/cart. - Problèmes SameSite : les redirections vers le fournisseur de paiement ou les flux embarqués se comportent différemment si les cookies ne sont pas marqués correctement.
- En‑têtes déjà envoyés : warnings PHP ou sortie peuvent empêcher la définition fiable des cookies. Oui, ce vieux plugin peut toujours ruiner votre journée.
2) Mise en cache de pages : servir du HTML « vide panier » périmé
La mise en cache de pages est excellente… jusqu’à ce qu’elle ne le soit plus. Les pages WooCommerce doivent être traitées comme personnalisées quand l’utilisateur a une session de panier. Les échecs typiques :
- URLs panier et checkout mises en cache (CDN, Varnish, Nginx FastCGI cache, plugin de cache).
- Le cache varie selon le cookie de connexion WordPress mais pas selon le cookie de session WooCommerce. Les visiteurs avec panier se voient servir la version « sans panier ».
- Endpoint des fragments de panier mis en cache (
?wc-ajax=get_refreshed_fragments), donnant un mini‑panier vide même si l’état serveur existe. - « Optimiser pour mobile » met en cache séparément mais n’inclut pas les cookies dans la clé de cache, divisant le comportement entre appareils.
3) Object cache : hypothèses Redis/Memcached et éviction
L’object cache ne stocke généralement pas le panier lui‑même, mais il stocke des éléments dont WooCommerce dépend : données client, produits, zones d’expédition, fragments, transients et parfois des aides liées aux sessions. Problèmes observés :
- Éviction Redis sous pression mémoire : les clés disparaissent, le comportement devient incohérent et le panier « se réinitialise parfois ».
- Object cache non persistant entre nœuds : chaque nœud a son propre cache local ; le comportement diffère selon le nœud sollicité.
- Drop‑in défectueux (
object-cache.php) qui ne gère pas correctement les groupes ou est incompatible avec votre version de WooCommerce.
4) Stockage de sessions : problèmes de table DB, nettoyage et latence de réplication
La table de sessions de WooCommerce est généralement dans MySQL/MariaDB. Ça fonctionne — jusqu’à ce que ça ne fonctionne plus : lenteurs, verrous ou lecture sur une réplique en retard. Modes de défaillance :
- Lecture/écriture séparées avec latence de réplication : add-to-cart écrit sur le primaire, l’actualisation lit sur la réplique qui n’a pas encore reçu les données, donc la session semble vide.
- Nettoyage trop agressif : sessions supprimées trop tôt à cause de TTL ou d’un job planifié défectueux.
- Corruption de table ou index manquants : les recherches de session deviennent lentes ; les timeouts peuvent pousser WooCommerce à se comporter comme s’il n’y avait pas de session.
5) Load balancers et WordPress multi-nœuds : le syndrome « ça marche sur un nœud »
Classique : vous ajoutez un second serveur web et soudainement les paniers disparaissent. Ce n’est pas que WooCommerce est capricieux. C’est vous qui exécutez une application avec état comme si c’était un site statique.
- Pas de sessions persistantes plus stockage local uniquement pour quelque chose qui devrait être partagé.
- Sels/clefs différents entre nœuds, cassant la validation des cookies et provoquant le rejet des sessions.
- Versions de plugins différentes entre nœuds (oui, ça arrive) entraînant des comportements incohérents pour cookies/sessions.
6) Stockage et système de fichiers : les sessions ne sont pas le seul chemin d’écriture
Bien que les sessions WooCommerce soient par défaut sauvegardées en DB, votre environnement écrit toujours sur disque : logs, fichiers de cache, parfois caches de plugins. Un disque plein ou un système de fichiers en lecture seule peut créer des symptômes de « panier vide » indirectement (par ex. plugins qui échouent silencieusement, base de données qui n’écrit pas, PHP incapable de créer des fichiers temporaires).
Tâches pratiques : commandes, sorties et décisions (12+)
Voici les tâches que j’exécute en production. Chaque tâche a : commande, sortie typique, ce que ça signifie et la décision à prendre.
Tâche 1 : Confirmer le comportement de cache sur la page panier (en‑têtes)
cr0x@server:~$ curl -I https://shop.example.com/cart/
HTTP/2 200
date: Sat, 27 Dec 2025 10:22:11 GMT
content-type: text/html; charset=UTF-8
cache-control: public, max-age=3600
age: 842
x-cache: HIT
via: 1.1 varnish
Ce que ça signifie : Votre HTML de panier est mis en cache publiquement et servi depuis le cache. C’est une cause directe du « panier vide après actualisation » pour certains ou tous les utilisateurs.
Décision : Désactivez la mise en cache pour /cart, /checkout et /my-account à tous les niveaux (plugin cache, reverse proxy, CDN). Assurez‑vous aussi que le cache varie selon les cookies WooCommerce pour les pages dynamiques.
Tâche 2 : Vérifier si les cookies WooCommerce sont définis après l’ajout au panier
cr0x@server:~$ curl -I -c /tmp/cookies.txt -b /tmp/cookies.txt "https://shop.example.com/?add-to-cart=123"
HTTP/2 302
date: Sat, 27 Dec 2025 10:23:04 GMT
set-cookie: wp_woocommerce_session_9c1b2a3d4e5f6g7h=1%7C%7C1735300000%7C%7C1735296400%7C%7C0f...; expires=Mon, 29 Dec 2025 10:23:04 GMT; Max-Age=172800; path=/; secure; HttpOnly; SameSite=Lax
set-cookie: woocommerce_items_in_cart=1; path=/; secure; SameSite=Lax
set-cookie: woocommerce_cart_hash=8c4f...; path=/; secure; SameSite=Lax
location: https://shop.example.com/cart/
Ce que ça signifie : Les cookies sont définis avec path=/ et secure. C’est bon. Si vous ne voyez pas ces cookies, le panier ne persistera pas.
Décision : Si les cookies manquent, inspectez les warnings PHP/sorties, la configuration du domaine de cookie et les redirections HTTPS. Si les cookies existent mais ne sont pas renvoyés, vous avez un problème de politique de navigateur ou de mismatch de domaine.
Tâche 3 : Vérifier le mismatch de domaine de cookie via les cookies de réponse
cr0x@server:~$ curl -I https://www.shop.example.com/cart/
HTTP/2 200
date: Sat, 27 Dec 2025 10:24:01 GMT
set-cookie: wp_woocommerce_session_9c1b2a3d4e5f6g7h=...; path=/; secure; HttpOnly; SameSite=Lax
Ce que ça signifie : Si vos utilisateurs atterrissent sur shop.example.com et www.shop.example.com, vous définissez probablement des cookies séparés pour chaque hôte. Les utilisateurs « perdront » leur panier lors des redirections ou en naviguant entre ces hostnames.
Décision : Choisissez un hôte canonique, redirigez l’autre, et faites correspondre home/siteurl de WordPress. Évitez les configurations « parfois www ».
Tâche 4 : Détecter FastCGI cache sur Nginx pour panier/checkout
cr0x@server:~$ curl -I https://shop.example.com/checkout/ | egrep -i "x-cache|x-fastcgi-cache|cache-control|set-cookie"
cache-control: max-age=600
x-fastcgi-cache: HIT
Ce que ça signifie : Nginx sert du HTML de checkout mis en cache. Cela peut aplatir les paniers en « vide » ou faire voir à un utilisateur l’état d’un autre (pire).
Décision : Excluez les endpoints WooCommerce du FastCGI cache et assurez‑vous que la clé de cache varie selon le cookie de session WooCommerce quand c’est approprié.
Tâche 5 : Vérifier que la table de sessions WooCommerce existe et contient des données
cr0x@server:~$ mysql -e "SHOW TABLES LIKE '%woocommerce_sessions%';"
+--------------------------+
| Tables_in_wp (%sessions%)|
+--------------------------+
| wp_woocommerce_sessions |
+--------------------------+
Ce que ça signifie : La table existe. L’étape suivante est de vérifier les écritures et le comportement d’expiration.
Décision : Si elle n’existe pas, vous avez une installation/migration cassée, ou un plugin a changé le gestionnaire de sessions. Corrigez cela avant de toucher au caching.
Tâche 6 : Confirmer que les sessions sont écrites et pas expirées instantanément
cr0x@server:~$ mysql -e "SELECT session_key, session_expiry FROM wp_woocommerce_sessions ORDER BY session_expiry DESC LIMIT 3;"
+----------------------------------+---------------+
| session_key | session_expiry |
+----------------------------------+---------------+
| 9c1b2a3d4e5f6g7h | 1735300024 |
| 4aa02c0d1131c9b2 | 1735299980 |
| 1fbb9d3d8a2a4e1a | 1735299901 |
+----------------------------------+---------------+
Ce que ça signifie : Les timestamps d’expiration semblent raisonnables (dans le futur). Si vous voyez des expirations passées ou une fenêtre très courte, quelque chose purge les sessions trop agressivement.
Décision : Si l’expiration est incorrecte, vérifiez les réglages de session WooCommerce, le cron et tout job de nettoyage personnalisé. Vérifiez aussi la dérive d’horloge du serveur.
Tâche 7 : Vérifier la séparation lecture/écriture DB (latence de réplication)
cr0x@server:~$ mysql -e "SHOW SLAVE STATUS\G" | egrep "Seconds_Behind_Master|Slave_IO_Running|Slave_SQL_Running"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 18
Ce que ça signifie : La réplique accuse 18 secondes de retard. Si vos lectures pour les données de session vont sur la réplique, une actualisation juste après l’ajout au panier peut renvoyer « pas de session », c’est‑à‑dire panier vide.
Décision : Ne lisez pas les données critiques de session depuis des répliques. Pointez les lectures/écritures des sessions WooCommerce vers le primaire ou assurez la cohérence read‑your‑writes.
Tâche 8 : Vérifier si Redis évince des clés (instabilité de l’object cache)
cr0x@server:~$ redis-cli INFO memory | egrep "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
used_memory_human:1.92G
maxmemory_human:2.00G
mem_fragmentation_ratio:1.64
Ce que ça signifie : Redis tourne près de maxmemory avec une forte fragmentation. Si l’éviction est activée, des clés peuvent disparaître sous pression, provoquant un comportement erratique.
Décision : Augmentez la mémoire Redis, ajustez la politique d’éviction, réduisez l’empreinte du cache, ou déplacez l’usage intensif des transients ailleurs. Ne placez pas l’état e‑commerce à côté d’un cache affamé.
Tâche 9 : Confirmer la politique d’éviction Redis et les compteurs d’éviction
cr0x@server:~$ redis-cli CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
cr0x@server:~$ redis-cli INFO stats | egrep "evicted_keys|keyspace_hits|keyspace_misses"
evicted_keys:48219
keyspace_hits:18022411
keyspace_misses:2401120
Ce que ça signifie : evicted_keys est non nul et augmente, ce qui veut dire que Redis supprime des clés pour faire de la place. Si des plugins ou thèmes supposent que les objets en cache existent, vous obtenez une UX incohérente.
Décision : Arrêtez l’éviction dans des caches de production seulement si vous tolérez l’échec des écritures ; généralement mieux vaut dimensionner correctement et s’assurer que l’état critique du panier n’est pas uniquement en Redis.
Tâche 10 : Vérifier que tous les nœuds web partagent les mêmes salts WordPress
cr0x@server:~$ ssh web1 "grep -E \"AUTH_KEY|SECURE_AUTH_KEY|LOGGED_IN_KEY|NONCE_KEY\" -n /var/www/html/wp-config.php | sha256sum"
7f6b0a0b8b2a1b0c44d5d5f2d0a... -
cr0x@server:~$ ssh web2 "grep -E \"AUTH_KEY|SECURE_AUTH_KEY|LOGGED_IN_KEY|NONCE_KEY\" -n /var/www/html/wp-config.php | sha256sum"
2f1c7f0fd9d1c8e0ad0b3f1d9c... -
Ce que ça signifie : Les hashes diffèrent. C’est mauvais. La validation des cookies et le comportement lié à l’auth/session peuvent varier selon le nœud.
Décision : Uniformisez wp-config.php entre nœuds (idéalement via gestion de configuration). Redémarrez PHP‑FPM si nécessaire. Puis retestez les paniers.
Tâche 11 : Vérifier la stickiness du load balancer et l’alternance des backends
cr0x@server:~$ for i in {1..6}; do curl -sI https://shop.example.com/cart/ | awk -F': ' 'tolower($1)=="x-backend"{print $2}'; done
web2
web1
web2
web1
web2
web1
Ce que ça signifie : Les requêtes alternent entre les nœuds. Si le stockage de session n’est pas partagé ou cohérent, les paniers peuvent disparaître à l’actualisation selon le backend qui répond.
Décision : Mettez en place la persistance (pansement à court terme) ou corrigez l’état partagé (la vraie solution long terme). Pour WooCommerce, une table de sessions DB partagée suffit généralement si les lectures/écritures sont cohérentes et la latence maîtrisée.
Tâche 12 : Vérifier que PHP‑FPM n’abandonne pas de requêtes ou ne timeout pas pendant les écritures de session
cr0x@server:~$ sudo tail -n 60 /var/log/php8.2-fpm.log
[27-Dec-2025 10:21:58] WARNING: [pool www] server reached pm.max_children setting (20), consider raising it
[27-Dec-2025 10:22:03] WARNING: [pool www] child 1934, script '/var/www/html/index.php' (request: "POST /?wc-ajax=add_to_cart") execution timed out (120.000 sec)
Ce que ça signifie : Vous saturez les workers PHP‑FPM et timeoutez pendant l’add-to-cart AJAX. Si l’écriture échoue, l’actualisation suivante peut légitimement afficher un panier vide.
Décision : Corrigez la capacité : augmentez pm.max_children si CPU/RAM le permettent, optimisez les requêtes lentes, et empêchez les plugins en arrière‑plan de monopoliser les workers.
Tâche 13 : Vérifier les logs d’accès Nginx pour les fragments de panier ou anomalies
cr0x@server:~$ sudo grep -E "wc-ajax=get_refreshed_fragments|wc-ajax=add_to_cart" /var/log/nginx/access.log | tail -n 5
203.0.113.10 - - [27/Dec/2025:10:23:05 +0000] "POST /?wc-ajax=add_to_cart HTTP/2.0" 200 1324 "-" "Mozilla/5.0"
203.0.113.10 - - [27/Dec/2025:10:23:06 +0000] "GET /?wc-ajax=get_refreshed_fragments HTTP/2.0" 200 4012 "-" "Mozilla/5.0"
Ce que ça signifie : Le flux normal se produit. Si vous voyez des boucles 301/302, des 403 (WAF) ou des en‑têtes de cache suspects sur ces endpoints, le mini‑panier peut mentir.
Décision : Excluez ces endpoints AJAX du cache et assurez‑vous que votre WAF ne les bloque pas. Ils ne sont pas optionnels pour une UX saine.
Tâche 14 : Valider l’espace disque et le système de fichiers en lecture seule (sabotage ennuyeux)
cr0x@server:~$ df -h /var /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p2 100G 99G 1.0G 99% /
tmpfs 16G 16G 0 100% /tmp
Ce que ça signifie : Vous manquez d’espace. L’espace temporaire plein peut casser les uploads, plugins de cache, traitement d’images et parfois des opérations liées aux sessions selon la stack.
Décision : Libérez de l’espace maintenant. Puis mettez en place la supervision et une rotation des logs sensée. Ne laissez pas « no space left on device » se faire passer pour un bug WooCommerce.
Tâche 15 : Vérifier les en‑têtes no-cache spécifiques à WooCommerce (ils doivent exister sur les pages sensibles)
cr0x@server:~$ curl -I https://shop.example.com/checkout/ | egrep -i "cache-control|pragma|expires"
cache-control: no-store, no-cache, must-revalidate, max-age=0
pragma: no-cache
expires: Wed, 11 Jan 1984 05:00:00 GMT
Ce que ça signifie : Ces en‑têtes sont saines. Si vous voyez public ou un max-age long, votre couche de cache peut ignorer l’intention d’origine ou écraser les en‑têtes.
Décision : Faites en sorte que les couches de cache respectent les en‑têtes d’origine sur panier/checkout, ou appliquez des règles de bypass par chemin et par cookies.
Trois mini-récits d’entreprise issus du terrain
Mini-récit 1 : L’incident causé par une fausse hypothèse (l’histoire « les répliques conviennent pour les lectures »)
Ils avaient un beau diagramme d’architecture et une réalité moins propre. La stack était WordPress + WooCommerce derrière un load balancer, base de données scindée en primaire pour les écritures et réplique pour les lectures. Ça marchait pour les pages de blog et de produit. Les graphiques étaient beaux. Tout le monde se félicitait de la victoire « scale ».
Puis le panier a commencé à se vider. Pas toujours. Juste assez souvent pour faire chuter le chiffre d’affaires et engendrer des tickets de support au ton digne des plaintes sur les bagages d’avion. L’ingénieur on‑call a fait ce que font les on‑call : redémarrer PHP‑FPM, purger les caches, et regarder les logs jusqu’à ce que le café devienne mécanisme de coping.
La cause racine était une fausse hypothèse : « les lectures de session sont juste des lectures. » WooCommerce écrivait la session lors de l’ajout au panier sur le primaire, puis la page panier lisait sur la réplique parce que la requête ressemblait à une lecture. Avec la latence de réplication sous charge, l’enregistrement de session n’était pas encore là. Le site avait l’air d’avoir l’amnésie, mais seulement pendant les premières secondes après un changement.
La correction fut à la fois simple et politiquement délicate : arrêter de router les lectures de la table sessions WooCommerce vers la réplique. Ils ont mis en place une règle pour épingler ces requêtes au primaire. La conversion a remonté immédiatement. Personne n’a voulu en reparler à la revue d’architecture suivante, parce que le diagramme était devenu moins élégant.
Leçon : la cohérence read‑your‑writes bat la « séparation propre » quand les clients cliquent sur « Passer la commande ».
Mini-récit 2 : L’optimisation qui s’est retournée contre eux (la campagne « tout mettre en cache »)
Une initiative performance a traversé l’entreprise comme une tempête bien intentionnée. La directive était claire : augmenter le taux de hit de cache. Quelqu’un a ajouté des règles de cache agressives au reverse proxy et un réglage CDN pour mettre en cache le HTML des « pages dynamiques » avec un TTL court. Les pages produit sont devenues rapides. Le panier aussi—rapide à être faux.
Les clients ont signalé que leurs paniers se vidaient à l’actualisation. D’autres voyaient le compteur du panier dans l’en‑tête appartenir à quelqu’un d’autre. Ce second symptôme transforme un bug en réunion de sécurité. La cause : la clé de cache ne variait pas selon le cookie de session WooCommerce. Le CDN voyait /cart/ comme la même page pour tout le monde.
L’équipe a essayé « purge totale » chaque heure. Ils ont essayé de baisser le TTL à 10 secondes. Ils ont essayé d’ajouter une query string. Tout cela traitait une erreur de conception de cache comme si c’était un problème d’expiration. Ce n’était pas ça. Ils mettaient en cache du HTML personnalisé sans clé de personnalisation.
La vraie correction était peu glamoureuse : contourner le cache pour les pages panier/checkout/compte, et contourner le cache quand les cookies WooCommerce sont présents. Pour le reste, mettre en cache normalement. Le taux de hit a baissé. Le chiffre d’affaires a augmenté. Quel métrique voulez‑vous expliquer au CFO ?
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise (consistance de la config)
Une autre organisation avait trois nœuds web et l’habitude des « hot fixes ». Un ingénieur SSHait sur un nœud, modifiait wp-config.php, et déclarait la mission accomplie. Le suivant faisait la même chose sur un autre nœud. Au fil du temps, les nœuds ont dérivé comme des continents : salts différents, fichiers de plugins différents, réglages PHP INI légèrement différents.
La perte de panier semblait « aléatoire ». Ce n’était pas aléatoire ; c’était un chaos déterministe. Les utilisateurs ajoutaient au panier, actualisaient, tombaient sur un backend différent, et le cookie de session échouait la validation. Le système faisait ce qu’on lui demandait : rejeter des signatures inconnues et démarrer une nouvelle session. Bonjour le panier vide.
La correction était si ennuyeuse qu’elle a failli ne jamais arriver : ils ont arrêté de traiter les serveurs de production comme des animaux de compagnie. Ils ont mis la config sous contrôle de version, déployé le même wp-config.php sur tous les nœuds, et ajouté un check au démarrage qui vérifiait que les hashes des salts correspondaient. Ils ont aussi verrouillé le déploiement des plugins sur un artefact unique.
Rien de « innovant » n’en est sorti. Mais le taux d’incidents a chuté. Les gardes on‑call ont été moins sollicités. Et le panier a arrêté de se comporter comme un poisson rouge.
Petite blague #2 : si vos nœuds web ont des salts différents, votre cluster n’est pas « haute disponibilité ». C’est « choisissez votre propre aventure », sauf que la fin est toujours des tickets de support.
Erreurs courantes : symptôme → cause → correction
Voici la partie où vous arrêtez de deviner.
1) Symptom : Le panier se vide immédiatement à l’actualisation
Cause racine : Le cookie de session n’est pas renvoyé (mismatch domaine/HTTPS) ou la session n’est pas écrite.
Correction : Imposer un seul hostname canonique, forcer HTTPS, vérifier que les cookies incluent path=/, et vérifier les warnings PHP qui empêchent Set-Cookie. Valider la présence de wp_woocommerce_session_*.
2) Symptom : Le panier se vide seulement sur les pages panier/checkout
Cause racine : Ces pages sont mises en cache (CDN/Varnish/FastCGI/plugin de cache).
Correction : Contourner la mise en cache pour /cart, /checkout, /my-account et les endpoints AJAX WooCommerce. Confirmer que l’origine envoie no-store et que les caches le respectent.
3) Symptom : Le panier se vide « aléatoirement » en multi‑serveur
Cause racine : Incohérence entre nœuds (salts/config différents), stockage non partagé, ou basculement du load balancer sans cohérence de session partagée.
Correction : Rendre la configuration identique sur tous les nœuds (salts, plugins, versions WP). Assurer que le stockage des sessions WooCommerce est partagé et que les lectures sont cohérentes. Utiliser la stickiness seulement comme mitigation temporaire.
4) Symptom : Le panier se vide après la connexion
Cause racine : Cas limites de migration de session plus cache qui varie selon les cookies de connexion mais pas les cookies WooCommerce, ou mismatch de domaine de cookie.
Correction : Assurer le bypass du cache quand les cookies de session WooCommerce existent. Confirmer l’hôte canonique avant la connexion. Tester le flux de connexion avec et sans articles dans le panier.
5) Symptom : Le mini‑panier apparaît vide, mais la page panier montre des articles
Cause racine : Endpoint des fragments de panier mis en cache ou bloqué ; ou optimisation JS qui casse le rafraîchissement des fragments.
Correction : Exclure wc-ajax=get_refreshed_fragments du cache et des règles WAF. Vérifier la console navigateur et les réponses réseau.
6) Symptom : Le panier fonctionne, puis se vide après quelques minutes
Cause racine : Expiration/nettoyage de session trop agressif, dérive d’horloge serveur, ou éviction Redis impactant l’état de support.
Correction : Valider les timestamps d’expiration des sessions, le comportement de cron de nettoyage et la synchronisation NTP/heure. Vérifier les evicted_keys de Redis.
7) Symptom : Le panier se vide seulement dans certaines géographies
Cause racine : Règles de cache edge CDN différentes selon la région ; ou redirections géo‑spécifiques changeant hostname/protocole.
Correction : Standardiser les règles de redirection globalement. S’assurer que la clé de cache inclut les cookies pertinents ou bypasser les pages personnalisées partout, pas seulement sur le POP principal.
8) Symptom : Le panier se vide sous charge
Cause racine : Timeouts sur les requêtes add-to-cart, contention DB sur la table de sessions, ou saturation PHP-FPM.
Correction : Ajuster PHP-FPM, optimiser la DB (index, correction des requêtes lentes), et réduire la charge des plugins. Surveiller les timeouts et les 5xx spécifiquement pour les endpoints AJAX WooCommerce.
Checklists / plan étape par étape
Phase 1 : Reproduire et isoler (15–30 minutes)
- Reproduire en navigation privée sur desktop et mobile. Noter la page exacte où le panier disparaît.
- Tester l’hôte canonique : toujours utiliser le même hostname et HTTPS.
- Vérifier les en‑têtes sur
/cartet/checkoutpour déceler hits de cache et mauvais cache-control. - Vérifier les cookies après l’ajout au panier : confirmer que
wp_woocommerce_session_*est défini et renvoyé.
Phase 2 : Éliminer les mauvais caches (sans sacrifier la performance)
- Désactiver la mise en cache de page pour :
/cart//checkout//my-account//?wc-ajax=*
- Bypasser le cache quand les cookies WooCommerce existent :
woocommerce_items_in_cartwoocommerce_cart_hashwp_woocommerce_session_*
- Confirmer avec curl que les en‑têtes
Ageet de hit de cache disparaissent sur panier/checkout.
Phase 3 : Rendre les sessions fiables entre nœuds
- Assurer des salts identiques et une config uniforme sur tous les nœuds.
- Vérifier le comportement du load balancer : si les requêtes font du round‑robin, confirmer que le stockage de sessions est partagé et cohérent.
- Supprimer les lectures sur répliques pour les sessions WooCommerce et requêtes critiques si vous avez de la latence de réplication.
Phase 4 : Rendre le stockage ennuyeux (le meilleur type de stockage)
- Vérifier la santé de la DB : table de sessions existante, indexée et sans verrous sous charge.
- Vérifier la santé de Redis si utilisé : pas de tempêtes d’éviction, mémoire adéquate, politique sensée.
- Vérifier l’espace disque et les permissions ; éliminer les échecs d’écriture intermittents.
Phase 5 : Tests de régression à garder
- Add-to-cart → actualiser la page du panier → les articles sont toujours là.
- Add-to-cart → connexion → panier préservé.
- Add-to-cart → basculement entre
wwwet sanswwwne doit jamais se produire ; vérifier que ça n’arrive pas. - Add-to-cart → page checkout affiche articles et totaux ; le mini‑panier correspond.
- Répéter avec le CDN activé et désactivé pour vérifier que les règles au bord sont correctes.
FAQ
1) Pourquoi le panier se vide uniquement après actualisation, pas immédiatement ?
Parce que l’ajout au panier peut réussir (cookies définis, session écrite), mais l’actualisation est servie par une autre couche de cache ou un autre nœud backend qui ne voit pas cet état. L’actualisation révèle les erreurs de cache et de routage.
2) Dois‑je simplement désactiver tout le caching pour WooCommerce ?
Non. Cachez agressivement les pages produit/catégorie, mais traitez panier/checkout/compte comme personnalisés. La désactivation globale laisse de l’argent sur la table et pénalise inutilement vos origins.
3) Est‑ce généralement causé par un plugin ?
Souvent, oui — mais pas « WooCommerce est buggy ». Les coupables courants sont les plugins de cache, les plugins de sécurité qui réécrivent les en‑têtes, et les plugins « d’optimisation » qui minifient/diffèrent les scripts et cassent les fragments de panier.
4) Ai‑je besoin de sessions persistantes (sticky) sur le load balancer ?
La stickiness peut masquer les problèmes, mais ce n’est pas la solution idéale. La meilleure réponse est un stockage de sessions partagé et cohérent et une configuration identique sur tous les nœuds. Utilisez la stickiness comme mitigation à court terme pendant un incident.
5) Redis peut‑il provoquer la perte de panier ?
Indirectement. Si vous stockez des états critiques dans Redis ou comptez sur des helpers en cache et que Redis évince des clés sous pression mémoire, le comportement devient incohérent. Corrigez le dimensionnement et la politique d’éviction, et assurez‑vous que l’état critique du panier n’est pas uniquement « cache‑seulement ».
6) Pourquoi ça arrive plus sur mobile ou Safari ?
Les règles de cookie sont plus strictes et la prévention du tracking est plus agressive. Si vous avez des redirections cross‑domain, un protocole mixte ou des paramètres SameSite étranges, les navigateurs mobiles vous puniront en premier.
7) Comment savoir si le CDN met en cache ma page panier ?
Regardez les en‑têtes : Age, les en‑têtes de statut de cache CDN, et tout indicateur HIT. Comparez aussi les corps HTML entre deux clients différents ; s’ils correspondent de manière suspecte, vous mettez en cache du contenu personnalisé.
8) La performance de la base de données peut‑elle faire « vider » le panier ?
Oui. Si les écritures de session timeoutent ou si les lectures sont assez lentes pour échouer, WooCommerce peut repartir sur une nouvelle session. Sous charge, cela ressemble à « panier qui se vide aléatoirement ». Vérifiez les timeouts PHP‑FPM et les logs des requêtes lentes DB.
9) Mon panier se vide seulement après la connexion. Quelle est la correction la plus rapide ?
D’abord, assurez‑vous de ne pas changer d’hôte/protocole pendant la connexion. Ensuite, bypasser le cache quand les cookies de session WooCommerce sont présents. Enfin, confirmer que les salts correspondent entre nœuds pour que les cookies de connexion soient validés de façon cohérente.
10) Quelle est la cause racine la plus fréquente ?
La mise en cache incorrecte des pages panier/checkout ou l’absence de variation du cache par les cookies WooCommerce. C’est le gain de performance le plus simple à mettre en place et la façon la plus rapide de casser le chiffre d’affaires.
Conclusion : prochaines étapes qui ne gâcheront pas votre week-end
Corriger « le panier qui se vide après actualisation » tient surtout à la discipline autour de l’état. Commencez par le diagnostic rapide : confirmez si vous perdez des cookies/sessions ou si vous servez du HTML mis en cache. Ensuite, retirez la mise en cache de quelques endpoints qui doivent être dynamiques. Après cela, rendez le comportement multi‑nœuds ennuyeux : config identique, état partagé et pas de surprises de latence de réplique.
Prochaines étapes pratiques :
- Vérifier les en‑têtes sur
/cartet/checkoutet éliminer les hits de cache là‑bas. - Vérifier que les cookies WooCommerce sont définis et renvoyés sur l’hôte HTTPS canonique.
- Auditer le comportement du load balancer et la dérive de configuration entre nœuds (surtout les salts).
- Valider les écritures dans la table de sessions WooCommerce et s’assurer que les lectures ne vont pas vers des répliques en retard.
- Vérifier l’éviction Redis et les timeouts PHP‑FPM si le problème apparaît sous charge.
Faites ces cinq choses, et vous passerez généralement de « amnésie mystérieuse du panier » à un checkout stable. Ce qui est tout l’intérêt de faire tourner une boutique.