« Chaussures Lila » avait vécu un Black Friday douloureux l’année précédente : au pic de trafic, le tunnel de commande mettait parfois plus de dix secondes à confirmer un paiement, le temps que toutes les actions déclenchées à la validation d’une commande — envoi d’e-mail, mise à jour du stock, synchronisation vers l’ERP, génération de facture — s’exécutent de façon synchrone, dans la même requête HTTP que le client attendait. Ce délai n’était volontairement pas résolu par un simple changement d’hébergement, sujet traité ailleurs, mais par une refonte du parcours de traitement lui-même.
Le diagnostic a mis en évidence un problème d’architecture, pas seulement de puissance serveur : chaque commande déclenchait, dans la foulée du hook woocommerce_thankyou, une dizaine d’actions coûteuses exécutées les unes après les autres, avant même que la page de confirmation ne s’affiche au client.
Le principe retenu : séparer la confirmation du traitement
La solution ne consiste pas à accélérer chaque action individuellement, mais à changer leur moment d’exécution : seules les actions strictement nécessaires à l’affichage immédiat de la confirmation restent synchrones, tout le reste passe dans une file de tâches en arrière-plan, traitée par le planificateur, quelques secondes après la confirmation visible au client.
WooCommerce embarque nativement Action Scheduler, la bibliothèque de planification de tâches également utilisée par de nombreuses extensions du même écosystème, ce qui a évité d’ajouter une dépendance externe comme une file Redis ou RabbitMQ, jugée disproportionnée pour le volume de la boutique.
Mise en œuvre : reporter les actions lourdes
Chaque action coûteuse a été retirée du hook synchrone et reprogrammée via as_schedule_single_action(), avec un déclenchement quasi immédiat mais hors du cycle de requête du client :
remove_action( 'woocommerce_thankyou', 'cl_synchroniser_erp_ancien' );
add_action( 'woocommerce_thankyou', 'cl_planifier_traitement_arriere_plan' );
function cl_planifier_traitement_arriere_plan( $order_id ) {
as_schedule_single_action(
time() + 5,
'cl_traiter_commande_arriere_plan',
array( 'order_id' => $order_id ),
'chaussures-lila-commandes'
);
}
add_action( 'cl_traiter_commande_arriere_plan', 'cl_executer_traitement_lourd' );
function cl_executer_traitement_lourd( $order_id ) {
$order = wc_get_order( $order_id );
cl_synchroniser_vers_erp( $order );
cl_generer_facture_pdf( $order );
cl_notifier_entrepot( $order );
}

Ce qui doit rester synchrone, malgré tout
Toutes les actions ne peuvent pas être différées sans risque. La décrémentation du stock reste synchrone, exécutée sur woocommerce_reduce_order_stock sans modification, car différer cette étape aurait ouvert une fenêtre de survente en cas de rafale de commandes simultanées sur un article à faible stock, un risque jugé bien plus grave qu’un tunnel légèrement plus lent.
- Décrémentation du stock : reste synchrone, non négociable
- Envoi de l’e-mail de confirmation client : reste synchrone, attente client forte
- Synchronisation ERP, génération de facture, notification entrepôt : différées
Dimensionner le nombre de workers
Action Scheduler traite ses tâches par lots, avec un nombre de tâches simultanées configurable via le filtre action_scheduler_queue_runner_concurrent_batches. La valeur par défaut, pensée pour un trafic ordinaire, s’est révélée insuffisante le jour du pic : la file s’accumulait plus vite qu’elle ne se vidait, créant un nouveau goulot d’étranglement, différé mais bien réel.
add_filter( 'action_scheduler_queue_runner_concurrent_batches', function() {
return 5; // valeur par défaut : 3
} );
Un test de charge avant le jour J
Deux semaines avant le Black Friday, un test de charge simulant 300 commandes en dix minutes a permis de mesurer le temps de vidage réel de la file, et d’ajuster ce paramètre progressivement jusqu’à obtenir un délai de traitement en arrière-plan restant sous la minute, même au pic simulé.
Résultat le jour du Black Friday
Le temps de réponse moyen du tunnel de paiement au pic de trafic est passé d’environ douze secondes l’année précédente à un peu moins de trois secondes, essentiellement le temps de communication avec le prestataire de paiement lui-même, plus aucune action métier lourde ne s’exécutant dans le cycle de requête client.
Un client qui attend dix secondes après avoir cliqué sur « payer » ne se dit jamais « la boutique traite ma commande soigneusement », il se dit « ça a peut-être planté », et recommence parfois le paiement.
En résumé
Absorber un pic de commandes n’est pas toujours affaire d’hébergement plus puissant : séparer ce qui doit répondre immédiatement de ce qui peut attendre quelques secondes, via Action Scheduler déjà présent dans WooCommerce, a suffi à transformer l’expérience du tunnel de paiement, sans changement d’infrastructure ni budget supplémentaire.