Quelque part dans chaque contrat d'intégration se trouve une phrase du type « chaque commande sera transmise exactement une fois ». Ce n'a jamais été vrai, pas une seule fois. Le réseau s'est partitionné en plein milieu d'une requête et l'émetteur a relancé ; la file d'attente a redistribué le message après le crash d'un consommateur ; un opérateur d'entrepôt a appuyé deux fois sur le bouton d'export. Les doublons ne sont pas un mode de défaillance - ce sont les intempéries.
Des clés d'idempotence, choisies avec soin
La solution est ancienne et peu glamour : chaque message porte une clé, et le traitement est un no-op quand la clé a déjà été vue. Toutes les décisions intéressantes résident dans le choix de la clé.
- Les clés naturelles battent les clés générées. Une synchronisation de commande indexée sur
order_id + statussurvit à la régénération de sa boîte d'envoi par l'émetteur ; un UUID aléatoire créé au moment de l'envoi n'y survit pas. - Rattachez la clé à l'effet, pas au message. Si un message crée une facture et réserve du stock, ce sont deux effets avec deux clés - sinon, un échec partiel vous empêche de relancer l'un ou l'autre en toute sécurité.
- Faites expirer les clés délibérément. Un magasin de déduplication qui grossit indéfiniment est une bombe à retardement ; un qui expire trop tôt réintroduit des doublons. Nous appliquons par défaut 3 fois l'horizon maximal de relance de l'émetteur.
Le test qui compte
Chaque intégration que nous livrons passe ce que nous appelons en interne le test du double-tap : rejouer l'intégralité du journal des messages d'hier contre le système d'aujourd'hui, deux fois, et comparer l'état résultant. Si quoi que ce soit a changé lors du deuxième passage, le pipeline n'est pas terminé.
C'est un test brutal et il échoue constamment pendant le développement - sur les horodatages, sur les champs d'audit « créé par », sur les compteurs de séquence. Chaque échec est un endroit où une redistribution à 3 heures du matin aurait discrètement corrompu des données. Il est bien moins coûteux de le détecter en développement qu'en production.