Le grossiste en fournitures de bureau à l’origine de ce projet gérait ses stocks et ses tarifs négociés par client dans un ERP métier spécialisé, mis à jour en continu par plusieurs entrepôts répartis sur le territoire. Le site e-commerce, construit en headless avec WooCommerce comme couche de gestion de commandes et un front Next.js, ne pouvait tolérer un décalage de stock affiché supérieur à quelques secondes : un client professionnel commandant une quantité en rupture aurait immédiatement remis en cause la fiabilité du site.
La question d’architecture centrale de ce projet n’était donc pas de savoir comment afficher un stock, mais comment le maintenir synchronisé à l’échelle de la seconde entre trois systèmes distincts : l’ERP, WordPress, et le navigateur du visiteur, sans jamais faire de WordPress une source de vérité concurrente de l’ERP.
Le flux de données retenu
L’ERP reste la seule autorité sur les niveaux de stock et les prix négociés. À chaque changement significatif, il envoie un webhook vers un endpoint WordPress dédié, qui met à jour une métadonnée de produit WooCommerce (_stock_temps_reel) sans jamais déclencher les hooks lourds habituels de WooCommerce (recalcul de disponibilité complet, notifications de réapprovisionnement), pour garder cette écriture rapide.
add_action('rest_api_init', function () {
register_rest_route('erp/v1', '/stock', [
'methods' => 'POST',
'callback' => 'erp_mettre_a_jour_stock',
'permission_callback' => 'erp_verifier_signature_hmac',
]);
});
function erp_mettre_a_jour_stock(WP_REST_Request $req) {
$sku = $req->get_param('sku');
$quantite = (int) $req->get_param('quantite');
$product_id = wc_get_product_id_by_sku($sku);
update_post_meta($product_id, '_stock_temps_reel', $quantite);
do_action('stock_temps_reel_modifie', $product_id, $quantite);
return new WP_REST_Response(['ok' => true], 200);
}
Pourquoi Server-Sent Events plutôt que WebSocket
Le flux d’information, dans ce projet, est strictement unidirectionnel : le serveur pousse des mises à jour de stock vers les navigateurs connectés, jamais l’inverse. Un WebSocket, techniquement capable de gérer ce cas, aurait imposé de gérer une connexion bidirectionnelle et son cycle de vie complet (reconnexion, ping-pong de maintien de connexion) pour un besoin qui n’utilise jamais le sens montant. Les Server-Sent Events, protocole plus simple reposant sur une connexion HTTP classique maintenue ouverte, correspondaient exactement à ce besoin, avec une implémentation nettement plus légère côté serveur.

// Route API Next.js exposant le flux SSE
export async function GET() {
const stream = new ReadableStream({
start(controller) {
const gestionnaire = (productId, quantite) => {
controller.enqueue(
`data: ${JSON.stringify({ productId, quantite })}\n\n`
);
};
busStock.on('modification', gestionnaire);
},
});
return new Response(stream, {
headers: { 'Content-Type': 'text/event-stream' },
});
}
Côté navigateur, l’API native EventSource gère nativement la reconnexion automatique en cas de coupure réseau, sans code supplémentaire à écrire pour ce cas précis, un avantage pratique déterminant face à un WebSocket qui aurait demandé cette logique à la main.
Le pont entre le webhook WordPress et le flux SSE
WordPress ne maintient aucune connexion persistante avec les navigateurs : à chaque webhook reçu de l’ERP, il republie l’information via un second webhook léger vers un petit service Node dédié, qui, lui, maintient les connexions SSE ouvertes avec les navigateurs et republie l’événement à tous les clients abonnés au produit concerné.
Le mécanisme de réconciliation
Un flux à sens unique pose un problème structurel : que se passe-t-il si un navigateur perd sa connexion SSE pendant quelques secondes et manque une mise à jour de stock ? La solution retenue combine deux mécanismes complémentaires : à la reconnexion, le navigateur redemande immédiatement l’état complet du stock via un appel REST classique, servant de filet de sécurité, avant de reprendre l’écoute du flux SSE pour les mises à jour suivantes.
- Le flux SSE gère les mises à jour incrémentales en temps réel pour l’expérience visuelle fluide.
- Un appel REST classique, déclenché à chaque reconnexion et toutes les cinq minutes en tâche de fond, garantit qu’aucun décalage durable ne peut s’installer même en cas de coupure prolongée.
Résultats mesurés en production
Le délai moyen entre un changement de stock enregistré côté ERP et son affichage effectif côté navigateur, mesuré sur l’ensemble de la chaîne, s’établit à 800 millisecondes en conditions normales, une latence jugée largement suffisante par le client au regard de son besoin métier initial de quelques secondes maximum.
Le temps réel n’impose pas systématiquement un WebSocket ; la première question à se poser est toujours celle du sens réel du flux d’information, avant de choisir l’outil qui le transporte.
Ce qu’on retient
Ce projet illustre une architecture où WordPress ne joue plus le rôle de source de vérité mais de relais synchronisé, un rôle différent de son usage habituel mais parfaitement cohérent dès lors que la source de vérité réelle, ici l’ERP, reste clairement identifiée et jamais remise en cause. La discipline à conserver est de toujours prévoir un mécanisme de réconciliation explicite dès qu’un flux temps réel unidirectionnel est mis en place, pour ne jamais dépendre uniquement de sa continuité parfaite.