ediverse Explorer la plateforme

À la une PEPPOL BIS Billing 3.0 L’obligation européenne d’e-invoicing arrive : France sept 2026, Belgique janv 2026, Allemagne 2025.

Idempotency Key (côté émetteur)

Le pendant émetteur du Idempotent Receiver. Sans clé d'idempotence stable côté émetteur, la déduplication côté récepteur ne sert à rien.

Problème

Un retry naïf qui régénère un nouveau UNB CTRL, un nouveau ISA13 ou un nouveau eb:MessageId à chaque tentative casse complètement le pattern Idempotent Receiver : le partenaire reçoit deux clés différentes, conclut qu'il s'agit de deux commandes distinctes et intègre deux fois. Le pattern d'idempotence ne suffit pas côté récepteur — il doit être amorcé côté émetteur.

Forces

  • Persister la clé est non-négociable. Un compteur en mémoire est perdu au redémarrage : la clé doit vivre dans une base, dans une outbox ou dans le journal d'envoi.
  • La clé doit être générée avant le premier envoi, pas à l'envoi. Sinon un crash après l'envoi mais avant la persistance laisse le système incapable de retenter avec la même clé.
  • Une clé unique par intention métier, pas par tentative réseau. Une commande métier = une clé, peu importe le nombre de retries.
  • La clé doit être contractuelle. L'émetteur et le récepteur doivent s'accorder sur sa structure, sa longueur et sa fenêtre d'unicité (souvent 90 jours en EDI).

Solution

Au moment où l'application métier décide d'émettre un message, elle génère une clé d'idempotence déterministe (typiquement <type>-<date>-<compteur> ou un UUID v4 persisté), la stocke avec le message à émettre dans une outbox, puis laisse le sender worker l'utiliser comme UNB CTRL / ISA13 / eb:MessageId à chaque tentative. Le code naïf devient un workflow à deux étapes : enregistrer l'intention (avec sa clé), puis exécuter l'envoi (qui peut être retenté autant de fois qu'il le faut avec la même clé).

plaintext idempotency-key-flow.txt
T0  Application métier → outbox.insert(domainEvent, idempotencyKey=ORD-20260514-0001)
T1  Sender worker → SELECT ... FROM outbox WHERE status='pending'
T2  Sender worker → POST AS2 avec UNB CTRL = ORD-20260514-0001
T3  réseau ↛ erreur réseau, pas de MDN reçu
T4  Sender worker → retry (mêmes octets) en réutilisant la même clé
T5  partenaire reconnaît un doublon (Idempotent Receiver) → réémet le même MDN
T6  Sender worker → outbox.markDelivered(idempotencyKey)

Implémentation EDI

En EDI, le sender worker lit l'outbox, prend le tuple (idempotencyKey, payload), écrit la clé dans le segment d'enveloppe correspondant (UNB+...+ORD-20260514-0001' en EDIFACT, ISA13=900042001 en X12, eb:MessageId en AS4) et l'envoie. Une retransmission rejoue la même ligne d'outbox avec la même clé. La table d'outbox porte un statut (pending, sent, acked) et une colonne de tentatives, pour observer les redondances réseau. Walmart, Stellantis, OpenPEPPOL imposent tous une clé d'idempotence stable côté émetteur dans leurs manuels partenaires.

Anti-patterns

  • Nouvelle clé à chaque retry. Annihile la déduplication côté récepteur — c'est exactement ce que le pattern doit empêcher.
  • Compteur en mémoire. Crash = compteur réinitialisé = collisions ou duplications.
  • Clé générée à l'envoi, pas avant. Si le worker crashe entre l'envoi et la persistance, on perd la traçabilité du retry.
  • Clé déconnectée de l'intention métier. Si la même commande peut produire deux clés, on se prive du bénéfice de l'idempotence.

Patterns liés

Sources