WooCommerce HPOS : ce que change le stockage haute performance des commandes, et comment migrer

par Francis Rozange | Oct 2, 2026 | WooCommerce

Chez Universal Yums, une entreprise américaine qui expédie chaque mois une boîte de friandises d’un pays différent, le tableau de bord des clients a commencé à ralentir vers quatre ou cinq millions de commandes. La boutique tournait sous WooCommerce, et chaque commande y était rangée comme une publication WordPress, à côté des articles et des pages, avec ses détails éparpillés dans une table de métadonnées géante.

HPOS, pour High-Performance Order Storage, est la réponse de WooCommerce à ce problème : un stockage des commandes dans des tables dédiées, conçues pour elles. Stable depuis la fin de 2023, il est activé par défaut sur les nouvelles boutiques, sauf si un plugin incompatible ou non déclaré l’en empêche. Les boutiques plus anciennes doivent encore faire le pas elles-mêmes.

Ce guide explique ce que HPOS change, ce que la version 8.2 a modifié et ce qu’elle n’a pas modifié, le rôle du mode de compatibilité, la vérification des plugins, la migration pas à pas, les commandes WP-CLI utiles, le retour en arrière, les adaptations de code, et les gains réels de performance. Il raconte aussi comment Universal Yums a migré plus de dix millions d’enregistrements.

Pourquoi WooCommerce a sorti les commandes de wp_posts

Des commandes rangées comme des articles

Pendant plus de dix ans, WooCommerce a stocké chaque commande comme une publication WordPress, dans la table wp_posts. Le montant, l’adresse, le moyen de paiement et des dizaines d’autres informations partaient dans wp_postmeta, une table de paires clé et valeur partagée avec tous les contenus du site.

Ce modèle avait l’avantage de la simplicité. Il a montré ses limites avec le volume : chaque recherche de commande par client ou par adresse électronique obligeait la base à fouiller une table de métadonnées dont les valeurs ne sont pas indexées. Sur une grosse boutique, cette table dépasse facilement des millions de lignes.

Les quatre tables de HPOS

HPOS range les commandes dans quatre tables dédiées. La table wc_orders porte l’essentiel : statut, devise, montant total, client, adresse électronique de facturation, dates, moyen de paiement. La table wc_order_addresses stocke une ligne par adresse, facturation et livraison.

La table wc_order_operational_data garde les données de fonctionnement, comme la clé de commande, la version de WooCommerce ou la date de paiement. Enfin, wc_orders_meta accueille les métadonnées que les plugins ajoutent, avec des valeurs indexées, à la différence de wp_postmeta. Les lignes de commande restent dans les tables woocommerce_order_items qu’utilisait déjà WooCommerce.

Les publications de remplacement et l’identifiant des commandes

Même avec HPOS actif, chaque commande garde une ligne dans wp_posts : une copie complète tant que la synchronisation tourne, puis une publication de remplacement, de type shop_order_placehold, quand elle est coupée ou après un nettoyage. Elle réserve l’identifiant, si bien que le numéro d’une commande reste égal à celui de sa publication. Ces traces restent en place même après le nettoyage des anciennes données.

Ce que la version 8.2 a changé, et ce qu’elle n’a pas changé

Le choix par défaut des nouvelles boutiques, sous conditions

HPOS existait en option expérimentale depuis WooCommerce 7.1, en novembre 2022. La version 8.2, publiée le 10 octobre 2023, l’a déclaré stable et l’a activé par défaut pour les nouvelles installations.

Le code pose toutefois deux conditions : la boutique ne doit contenir aucune commande, et aucun plugin actif qui se déclare lié à WooCommerce ne doit être incompatible ou muet sur le sujet. Une installation neuve avec un plugin non déclaré démarre donc sur l’ancien stockage.

Les boutiques existantes : toujours un choix en 2026

La documentation destinée aux marchands est claire : les boutiques existantes ne sont pas migrées automatiquement, la fonction reste entièrement optionnelle. En octobre 2026, nous n’avons trouvé aucune date officielle de retrait du stockage par publications. Méfiez-vous des articles qui annoncent sa suppression prochaine : WooCommerce n’a rien publié de tel.

Le réglage se trouve dans WooCommerce, Réglages, Avancé, Fonctionnalités. La rubrique « Stockage des données de commande » propose deux choix : « Stockage des commandes haute performance (recommandé) » et « Stockage des publications WordPress (ancien) ». En dessous, une case active le mode de compatibilité.

Le mode de compatibilité et la synchronisation

Tables de référence et tables de secours

À tout moment, un seul des deux stockages fait référence : c’est lui que WooCommerce lit et écrit. Le mode de compatibilité ajoute une synchronisation vers l’autre stockage, qui sert alors de copie de secours.

Tant que la synchronisation tourne, le retour à l’ancien stockage est instantané. La synchronisation de fond passe par des tâches planifiées d’Action Scheduler, visibles dans WooCommerce, État, Actions planifiées. WooCommerce interdit de changer de stockage tant que des commandes restent à synchroniser, avec un avertissement sans ambiguïté sur le risque de corruption des données.

La synchronisation à la lecture, coupée depuis la version 10.7

Une seconde mécanique, la synchronisation à la lecture, recopiait dans HPOS les modifications qu’un plugin écrivait directement dans les anciennes tables, au moment où la commande était lue. Elle a causé plusieurs incidents documentés.

En novembre 2024, un ticket décrit des commandes qui passent mystérieusement en attente et perdent leurs métadonnées, corrigé dans le code en octobre 2025 et livré avec la version 10.4 en décembre 2025. En décembre 2025, un autre décrit des webhooks order.updated envoyés en boucle : la lecture d’une commande déclenchait une synchronisation, donc une modification, donc un nouvel envoi. La version 10.4.3 a corrigé cette boucle quelques jours plus tard.

WooCommerce en a tiré la conclusion. Depuis la version 10.7, publiée le 14 avril 2026, la synchronisation à la lecture est désactivée par défaut, et l’équipe rappelle que le mode de compatibilité comme cette synchronisation n’ont jamais été que des mesures de transition. La copie dans les anciennes tables doit être traitée en lecture seule. Un code qui écrit encore directement dans wp_postmeta est le vrai problème à corriger.

Les abonnements, un cas à surveiller

Les boutiques d’abonnements ont connu leur propre alerte. En avril 2026, Sybre Waaijer, fondateur du plugin The SEO Framework, a signalé publiquement quatre bogues de WooCommerce Subscriptions qui, selon lui, laissaient des abonnements en renouvellement manuel. WooCommerce a confirmé les quatre, mais en limite la portée : deux seulement, combinés, produisaient cet effet. Le dernier a été corrigé dans la version 8.6.1 du plugin, le 23 avril.

Le 30 avril, WooCommerce a publié, sous la signature de Darren Ethier, un outil de vérification de l’état des abonnements. Selon ce récit, l’exposition concernait des boutiques sous HPOS, surtout d’octobre 2023 à mars 2024, avec une traîne jusqu’au 9 mai 2024. Si vous vendiez des abonnements sous HPOS pendant cette période, lancez l’outil.

Vérifier vos plugins avant de basculer

L’écran Fonctionnalités et la liste des plugins incompatibles

Les plugins déclarent leur compatibilité avec HPOS dans leur code. Si un plugin actif se déclare incompatible, WooCommerce désactive l’option HPOS dans l’écran Fonctionnalités et propose un lien vers la liste des plugins concernés.

Une subtilité compte beaucoup : seuls les plugins qui portent l’en-tête « WC tested up to » sont vérifiés. Pour ces plugins, l’absence de déclaration vaut incompatibilité. Un plugin sans cet en-tête n’est pas vérifié du tout, et il peut casser sans prévenir s’il écrit directement dans les anciennes tables.

La commande compatibility-info

WP-CLI dresse le même état des lieux en ligne de commande, depuis WooCommerce 9.1. La commande classe les plugins en compatibles, incompatibles et incertains.

wp wc hpos compatibility-info --include-inactive --display-filenames

Un plugin qui n’a toujours pas déclaré sa compatibilité en 2026 mérite une question directe à son éditeur, et souvent un remplaçant.

Le code sur mesure et les systèmes externes

Les plugins ne sont qu’une partie du sujet. Le code sur mesure du thème ou des plugins maison, les requêtes SQL écrites à la main, et les systèmes externes qui lisent directement la base, entrepôt de données, logiciel de comptabilité ou d’expédition, doivent aussi être audités. Le guide officiel pour les grandes boutiques rappelle que ces lecteurs externes échappent à un audit de code classique.

Migrer pas à pas

Tester en local, puis sur une copie de recette

Le guide de WooCommerce pour les grandes boutiques décrit trois phases. En local, testez la commande avec chaque moyen de paiement, les remboursements, les achats et renouvellements d’abonnements et vos parcours critiques, synchronisation active puis coupée.

Sur une copie de recette alimentée par la base de production, activez la synchronisation et mesurez sa durée. Sur la boutique de test de WooCommerce, neuf millions de commandes ont demandé environ une semaine. Si vous devez d’abord créer cette copie, notre méthode pour migrer un site WordPress sans interruption détaille la préparation.

Les plugins qui ont leurs propres types de contenu

La documentation destinée aux marchands ajoute une consigne facile à oublier : les plugins qui stockent leurs propres types de contenu liés aux commandes, comme WooCommerce Subscriptions ou WooCommerce Bookings, doivent rester actifs pendant toute la transition. Les désactiver avant la bascule peut créer des écarts entre les deux stockages.

La synchronisation de fond avance par lots. La documentation parle de vingt-cinq commandes à la fois, mais le code en traite deux cent cinquante quand les anciennes tables font référence, et vingt-six dans l’autre sens, plus lent. Un filtre permet d’ajuster cette taille si vos tâches planifiées ont de la marge.

En production : synchroniser, puis basculer

En production, activez la synchronisation en gardant les anciennes tables comme référence, puis lancez la migration. Interrompre la synchronisation est sans danger, d’après le guide. Une fois tout synchronisé, passez HPOS en référence en gardant la synchronisation active : le retour en arrière reste instantané, sans interruption de service.

wp wc hpos sync
wp wc hpos count_unmigrated
wp wc hpos enable --with-sync

Couper le mode de compatibilité, et quand

Sur sa propre boutique à fort volume, WooCommerce a coupé la synchronisation à la lecture au bout de six heures, puis toute la synchronisation au bout d’une semaine. L’équipe a ensuite relancé une synchronisation manuelle de temps en temps pour garder une solution de repli.

Le guide précise que garder la synchronisation active, avec les anciennes tables en référence, n’a pas eu d’effet négatif notable sur les performances. Cette observation vaut pour la phase où les anciennes tables font référence. Une fois HPOS en référence, le guide recommande de couper la synchronisation progressivement, et WooCommerce rappelle que couper le mode de compatibilité peut améliorer les performances. Une semaine de fonctionnement stable est le repère du guide.

Deux canaux de lumière parallèles qui se reflètent, reliés par de fins ponts lumineux

Les commandes WP-CLI qui comptent

status, sync et count_unmigrated

Depuis WooCommerce 8.9, toutes les commandes se trouvent sous wp wc hpos. Les anciennes commandes wp wc cot fonctionnent encore avec un avertissement, même si certaines pages de la documentation les citent toujours. La commande status donne l’état général : HPOS actif ou non, mode de compatibilité, commandes non synchronisées et commandes à nettoyer.

wp wc hpos status
wp wc hpos sync --batch-size=500

Notre sélection de commandes WP-CLI essentielles présente l’outil lui-même.

verify_data, diff et backfill pour diagnostiquer

La commande verify_data compare les anciennes tables et les tables HPOS, et ne sert donc que si le mode de compatibilité est actif. Attention à une coquille du guide officiel pour les grandes boutiques, qui cite une commande verify_cot_data sous wp wc hpos : elle n’existe pas sous ce nom.

wp wc hpos verify_data --verbose
wp wc hpos diff 1234
wp wc hpos backfill 1234 --from=hpos --to=posts

La commande diff montre les écarts d’une commande précise sans rien corriger, et backfill recopie une commande d’un stockage vers l’autre. L’option --re-migrate de verify_data mérite la prudence : le code avertit qu’elle peut écraser des données récentes par des données périmées.

Les tables HPOS et le périmètre de WP-CLI

Un piège guette ceux qui déplacent la base avec WP-CLI. Par défaut, des commandes comme wp db tables ou wp search-replace ne traitent que les tables que WordPress connaît. WooCommerce y inscrit une dizaine de ses tables, mais pas les quatre tables de HPOS.

Un remplacement de domaine peut donc oublier les données de commande qui le contiennent, comme des adresses web enregistrées dans les métadonnées ou des adresses électroniques sur l’ancien domaine. Ajoutez l’option --all-tables-with-prefix pour couvrir toutes les tables qui portent le préfixe du site.

cleanup, le point sans retour facile

La commande cleanup supprime les anciennes données des commandes, une fois HPOS en référence et la synchronisation coupée. Elle garde les publications de remplacement. Après elle, revenir à l’ancien stockage suppose de reconstruire chaque commande depuis HPOS : ne la lancez qu’après des semaines de fonctionnement sans incident.

Le cas Universal Yums : dix millions d’enregistrements

Devin Price, directeur technique d’Universal Yums, a raconté la migration de sa boutique sur son blog, DevPress, au printemps 2024. WooCommerce a ensuite présenté l’entreprise deux fois sur son propre site. L’histoire réunit tout ce que la documentation décrit, à une échelle qui en grossit chaque détail.

Une boutique d’abonnements à grande échelle

Au moment de la migration, la boutique comptait plus de dix millions de commandes et d’abonnements. Le premier jour de chaque mois, elle génère plus de cent vingt mille commandes de renouvellement. Avant HPOS, l’équipe avait accumulé les contournements : pour retrouver vite les commandes d’un client, elle rangeait son identifiant dans une colonne de wp_posts détournée de son usage.

Le plan choisi, sans mode de compatibilité

L’audit a commencé par le code. La plupart des plugins étaient déjà déclarés compatibles, mais la boutique comptait plus de cent mille lignes de code maison. Environ cinq cents tests automatisés ont repéré à eux seuls près de 80 % des fonctions à reprendre. Un plugin d’affiliation n’a jamais été mis à jour : l’équipe a écrit sa propre intégration.

Devin Price a ensuite écarté la voie standard. La double écriture du mode de compatibilité l’inquiétait, surtout si la migration de fond débordait sur un jour de renouvellements. Sur la copie de recette, la page de réglages de HPOS ne se chargeait même plus une fois la migration lancée, sans doute à cause du comptage des commandes en attente sur plus de dix millions d’enregistrements.

L’équipe a donc écrit son propre script, capable de migrer environ trois millions de commandes par heure. Elle a d’abord migré les commandes terminées et les abonnements annulés, puis supprimé leurs anciennes données. Une nuit, à trois heures, l’heure la plus creuse, la boutique est passée en maintenance pour migrer le reste et basculer sur HPOS. Les seuls soucis immédiats sont venus des nouvelles adresses des écrans de commande dans l’administration.

Le jour des renouvellements : les interblocages

Le vrai test est venu au premier cycle de renouvellements. Environ un quart des renouvellements a échoué. Le journal montrait des interblocages, ces situations où deux transactions se bloquent mutuellement, lors de l’insertion dans la table des adresses de commande. La commande de renouvellement n’était jamais créée.

L’équipe a d’abord rattrapé les abonnements touchés avec un script, puis réduit le nombre de lots qu’Action Scheduler traitait en parallèle. À vingt lots simultanés, un quart des renouvellements échouait. À dix lots, un sur dix. À cinq, un sur vingt, au prix d’un débit plus faible. En complément, un crochet replanifiait une minute plus tard tout renouvellement tombé sur un interblocage. Notre guide sur WP-Cron et le cron système explique comment Action Scheduler exécute ces tâches.

Ce que la version 9.0 a changé, et ce que la boutique a gagné

Fin mai 2024, Devin Price écrivait que l’équipe de WooCommerce, très réactive, publierait un correctif dans la version 9.0. Le 22 mai, une modification fusionnée pour cette version remplaçait justement la requête d’insertion de la table des adresses par une lecture suivie d’une insertion ou d’une mise à jour, qui pose moins de verrous, en citant le renouvellement d’abonnements.

Les deux sources ne se citent pas l’une l’autre, mais tout concorde. WooCommerce 9.0 est sortie le 18 juin 2024.

Le bilan se lit en deux temps. En mai 2024, sur DevPress, Devin Price écrivait n’avoir constaté aucun gain de performance notable, la boutique étant déjà très optimisée, et en attendait davantage pour les grandes boutiques sans équipe dédiée à la performance. En 2025, interrogé par WooCommerce, il explique que HPOS a permis de retirer tous les contournements, que le tableau de bord reste aussi rapide, et que HPOS a rendu les choses bien plus rapides.

Pour une boutique plus modeste, la leçon est double. Les tests automatisés et l’audit du code maison trouvent l’essentiel des problèmes. Et sauter le mode de compatibilité revient à renoncer au retour en arrière instantané. Une telle décision se justifie à cette échelle, et une boutique plus modeste a tout intérêt à garder le retour instantané.

Revenir en arrière

Avec le mode de compatibilité : instantané

Tant que la synchronisation est active, revenir à l’ancien stockage est immédiat. Activez le mode de compatibilité s’il ne l’est plus, attendez la fin de la synchronisation, choisissez « Stockage des publications WordPress (ancien) », puis enregistrez.

Synchronisation coupée ou nettoyage fait : reconstruire d’abord

Si la synchronisation est coupée, le retour reste possible, mais il faut attendre que les tâches de fond reconstruisent les anciennes tables. Après un cleanup, chaque commande doit être recopiée depuis HPOS. Dans tous les cas, une sauvegarde complète prise avant la bascule reste le dernier filet : notre comparatif des meilleurs plugins de sauvegarde vous aide à choisir l’outil.

Pour les développeurs : des fonctions de publication à l’API CRUD

Déclarer la compatibilité

Un plugin déclare sa compatibilité dans son fichier principal, pendant l’action before_woocommerce_init, comme le montre le guide officiel des développeurs.

add_action( 'before_woocommerce_init', function () {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
	}
} );

Passer false en troisième argument déclare au contraire une incompatibilité. Hors du fichier principal, remplacez __FILE__ par le chemin du plugin, comme mon-plugin/mon-plugin.php.

Remplacer get_post et update_post_meta

Toute lecture de commande passe par wc_get_order(), jamais par get_post(). Les métadonnées s’écrivent avec les méthodes de l’objet commande, suivies d’un enregistrement. Le guide rappelle que save() coûte cher et qu’il faut éviter de l’appeler pour rien.

$order = wc_get_order( $order_id );
$order->update_meta_data( '_mon_suivi', $tracking_number );
$order->save();

Pour savoir quel stockage est actif, la classe OrderUtil fournit custom_orders_table_usage_is_enabled(). Pour tester le type d’un objet, elle remplace get_post_type() par get_order_type().

Écrans d’administration, colonnes et boîtes

Sous HPOS, la liste des commandes passe à l’adresse admin.php?page=wc-orders, et l’écran d’une commande prend un nouveau format. Les boîtes ajoutées à l’écran de commande doivent viser l’identifiant d’écran renvoyé par wc_get_page_screen_id( 'shop-order' ), et les colonnes de la liste utilisent des crochets dédiés, comme manage_woocommerce_page_wc-orders_columns.

Les nouvelles boutiques et le choix par défaut

Un développeur qui livre des boutiques neuves peut influencer le choix initial. Le filtre woocommerce_enable_hpos_by_default_for_new_shops, présent depuis la version 8.2, décide si une installation sans commande démarre sous HPOS. Mieux vaut le laisser actif et corriger les plugins qui bloquent, puisque c’est sous HPOS que la boutique devra vivre.

Interroger les commandes

La fonction wc_get_orders() accepte des requêtes sur les métadonnées, sur les champs de commande et sur les dates, sur le modèle de WP_Query. Elle fonctionne avec les deux stockages, ce qui en fait le chemin sûr pour du code destiné à durer, à une réserve près : les requêtes sur les champs de commande, ajoutées avec HPOS, ne sont prises en charge que sous HPOS.

Les gains de performance à attendre

Ce que mesurent vraiment les chiffres officiels

WooCommerce annonce une création de commandes jusqu’à cinq fois plus rapide, une validation de commande jusqu’à une fois et demie plus rapide, et une recherche de commandes jusqu’à quarante fois plus rapide. Ces chiffres viennent d’un banc d’essai de mars 2023, sur une version de développement, avec environ quatre cent mille commandes et un seul processus.

Le gain de quarante fois concerne le filtre par client, sur une colonne indexée. La recherche par métadonnée gagnait environ dix fois, la recherche sur une colonne non indexée environ trois fois. Ces mesures donnent des ordres de grandeur obtenus dans des conditions précises, que votre boutique ne reproduira pas forcément.

Ce qui a suivi, et ce qu’en dit le terrain

HPOS continue de recevoir des optimisations propres. Depuis WooCommerce 10.4, un cache des commandes est sorti de la phase expérimentale, désactivé par défaut et recommandé avec un cache d’objets. En 10.7, une route de l’API des commandes est passée de 271 à 132 requêtes par appel sur les commandes HPOS.

Le témoignage d’Universal Yums est nuancé : peu après la migration, Devin Price ne voyait pas de gain notable sur une boutique déjà optimisée, et un an plus tard, il dit que HPOS a rendu les choses bien plus rapides et a permis de retirer les contournements. Pour accélérer réellement la commande, d’autres leviers comptent autant, comme le montre notre guide pour optimiser la page de commande WooCommerce.

Tableau récapitulatif

Étape Réglage ou commande Risque Vérification
Inventaire wp wc hpos compatibility-info Plugin non déclaré, code maison Liste des plugins incompatibles
Recette Copie de production, synchronisation Durée sous-estimée Temps de synchronisation mesuré
Synchronisation wp wc hpos sync Faible, interruption possible count_unmigrated à zéro
Bascule HPOS en référence, compatibilité active Retour instantané possible Parcours de commande complets
Fin de transition Mode de compatibilité coupé Retour plus lent wp wc hpos status
Nettoyage wp wc hpos cleanup Retour difficile Sauvegarde vérifiée avant

Questions fréquentes

HPOS est-il obligatoire ?

Non. Les boutiques existantes ne sont pas migrées automatiquement, et WooCommerce n’a annoncé aucune date de retrait de l’ancien stockage. C’est toutefois le stockage de référence pour l’avenir, et les nouvelles optimisations le visent.

Mes anciennes commandes migrent-elles toutes seules ?

Seulement si vous activez la synchronisation. Les tâches de fond copient alors les commandes par lots, ou la commande wp wc hpos sync s’en charge plus vite en ligne de commande.

Peut-on revenir en arrière ?

Oui. Avec le mode de compatibilité actif, le retour est instantané. Sans lui, il faut d’abord reconstruire les anciennes tables, et après un nettoyage, recopier chaque commande depuis HPOS.

Le mode de compatibilité ralentit-il la boutique ?

Tant que les anciennes tables font référence, le guide officiel n’a pas constaté d’effet négatif notable. Une fois HPOS en référence, la double écriture a un coût : WooCommerce indique que couper le mode de compatibilité peut améliorer les performances. Coupez-le une fois la bascule validée.

Que faire si un seul plugin est incompatible ?

Demandez une mise à jour à son éditeur, cherchez un remplaçant, ou faites adapter son code. Forcer l’activation malgré l’avertissement expose à des commandes incomplètes ou à des données manquantes.

Conclusion

HPOS range enfin les commandes là où elles doivent être, dans des tables pensées pour elles. La migration n’a rien d’automatique pour une boutique existante, et c’est une bonne chose : elle demande un inventaire des plugins et du code maison, une recette sur une copie, une synchronisation mesurée, puis une bascule avec retour possible.

Universal Yums a montré qu’une boutique de plus de dix millions d’enregistrements peut y arriver, et que les surprises viennent rarement de là où on les attend. Gardez le mode de compatibilité aussi longtemps que nécessaire, et ne lancez le nettoyage qu’une fois la confiance installée.

Sources


LaFactory conçoit, développe et maintient des sites WordPress et WooCommerce, et développe ses propres plugins. Parlons de votre projet WordPress.

Francis Rozange

Ancien chef de rubrique à Libération, il dirige LaFactory, agence web internationale depuis 1996.

Panier