19 - Pièges fréquents en event-driven
Les erreurs classiques sont souvent les mêmes. Les identifier rapidement permet d’éviter des mois de dettes techniques. Dans un contexte bancaire, ces pièges ne sont pas seulement techniques: ils peuvent entraîner des incohérences comptables ou des incidents de conformité.
Cet article propose une lecture structurée: symptôme, cause, remède. Chaque piège est illustré par un exemple bancaire.
1) Mauvaise clé de partition
Symptôme: ordre incohérent des opérations d’un compte.
Cause: partitionnement par customer_id au lieu de account_id.
Remède: aligner la clé de partition sur l’agrégat métier.
Exemple bancaire: un débit est traité avant un crédit, provoquant un solde
négatif temporaire et une alerte frauduleuse. Le correctif consiste à router
les events sur account_id pour préserver l’ordre des mouvements d’un compte.
2) Event notification qui cache un workflow
Symptôme: logique implicite difficile à tracer. Cause: utilisation d’un event comme commande déguisée. Remède: utiliser une command explicite pour les actions attendues.
Exemple bancaire: publier TransferInitiated en espérant que le ledger poste
immédiatement l’écriture, sans SLA. Le flux devient invisible et fragile.
3) Notification légère alors qu’un state transfer est requis
Symptôme: avalanche d’appels synchrones vers un service central. Cause: event trop léger (id seulement). Remède: transporter l’état nécessaire quand la résilience l’exige.
Exemple bancaire: BeneficiaryUpdated sans détail force l’app mobile à appeler
Core Banking en boucle, ce qui crée un point de congestion.
4) Payloads trop lourds
Symptôme: latence élevée, coûts de stockage. Cause: events contenant des snapshots complets inutiles. Remède: limiter le payload au contrat métier.
Exemple bancaire: inclure tout le profil client dans un event transactionnel alourdit le log et augmente le coût de replay.
5) Absence d’idempotence
Symptôme: doublons comptables.
Cause: consumers non idempotents.
Remède: déduplication par event_id et write idempotent.
Exemple bancaire: deux écritures identiques dans le ledger après un retry.
6) Schémas sans gouvernance
Symptôme: consumers cassés après déploiement. Cause: changements non versionnés. Remède: Schema Registry + compatibilité.
Exemple bancaire: renommer un champ amount sans versioning casse le reporting.
7) Mélanger commands et events
Symptôme: confusion sur le sens des messages. Cause: un même topic contient commandes et faits. Remède: topics séparés par intention.
Exemple bancaire: prod.transfer.all.v1 mélange commands et events, rendant
le debugging complexe et la sécurité floue.
8) Topic unique pour tout
Symptôme: gouvernance impossible. Cause: absence de découpage par domaine. Remède: séparer par domaine et type.
Exemple bancaire: tous les events dans prod.events rendent les ACLs inutiles.
9) Retention et compaction mal définies
Symptôme: perte d’historique ou coûts excessifs. Cause: configuration par défaut non adaptée. Remède: définir retention/compaction par use case.
Exemple bancaire: compacter un topic transactionnel détruit l’audit.
10) Sur-partitionnement
Symptôme: rebalances instables, coûts élevés. Cause: création de trop de partitions sans besoin réel. Remède: dimensionner selon le débit réel et la croissance.
11) Dual write sans outbox
Symptôme: incohérences entre base et Kafka. Cause: absence de Transactional Outbox. Remède: outbox ou CDC.
Exemple bancaire: virement enregistré mais event absent.
12) Asynchronisme partout
Symptôme: parcours client incohérents. Cause: aucune décision synchrone. Remède: garder le synchronisme pour les invariants critiques.
Exemple bancaire: API répond “virement accepté” alors que la validation AML n’a pas encore eu lieu.
13) Observabilité insuffisante
Symptôme: incidents difficiles à diagnostiquer. Cause: absence de correlation_id, métriques faibles. Remède: tracing et dashboards.
Exemple bancaire: impossible de reconstituer le parcours d’un virement litigieux.
14) DLQ comme flux normal
Symptôme: erreurs masquées. Cause: usage abusif de la DLQ. Remède: traiter la cause racine, pas la conséquence.
15) Effets externes lors des replays
Symptôme: notifications envoyées à nouveau ou écritures dupliquées. Cause: replay non isolé. Remède: gateway désactivable et journaux d’effets externes.
Pièges de conception (architecture)
Les pièges de conception apparaissent dès la modélisation. Ils concernent la frontière entre commandes et événements, la définition des agrégats et la structure des topics. Une erreur fréquente consiste à exposer un modèle interne comme contrat public: cela fige le domaine et rend chaque évolution coûteuse. Dans une banque, cela se traduit par des migrations longues et risquées, car plusieurs domaines (fraude, comptabilité, reporting) dépendent du même schéma.
Autre piège: confondre événement métier et événement technique. Publier des events techniques dans un flux métier rend la lecture confuse et pollue les projections. Les événements techniques doivent être isolés pour éviter un bruit constant qui masque les signaux importants.
Enfin, le choix du modèle d’intégration (notification légère vs state transfer) est souvent mal calibré. Un state transfer trop riche peut exposer des données sensibles; un event trop léger provoque des appels synchrones en cascade et annule une partie des bénéfices de l’event-driven.
Pièges d’exploitation (run et operations)
En production, les pièges les plus coûteux sont ceux liés au fonctionnement quotidien: rebalances instables, lag croissant, DLQ en explosion. Un flux bancaire critique doit être surveillé comme un service de paiement: métriques de lag, taux d’erreur, latence end-to-end. Sans observabilité, les incidents deviennent invisibles jusqu’à l’impact client.
Les replays sont un autre piège opérationnel. Sans stratégie claire, un replay peut déclencher des effets externes ou saturer les consumers. En banque, on prévoit des environnements de replay isolés et des modes “dry-run” pour reconstruire les projections sans effets réels.
Enfin, la gestion de capacité est souvent négligée. Un flux qui double de volume (fin de mois, campagnes) peut saturer un consumer group et créer un backlog critique. L’anticipation des pics est indispensable pour la stabilité.
Pièges de données (qualité et conformité)
Les données sont le carburant du système. Une dérive de schéma ou un champ mal interprété peut invalider des projections financières. En banque, les champs sensibles (montants, identifiants, IBAN) doivent être contrôlés et tokenisés si nécessaire.
La rétention est souvent mal définie. Conserver trop longtemps des événements personnels est un risque RGPD; compacter un flux transactionnel détruit l’historique d’audit. Ces choix doivent être alignés avec la conformité et les exigences métier.
Enfin, la qualité sémantique est essentielle: un montant négatif ou une devise invalide doit être bloqué en amont. Sans ces contrôles, la corruption se propage dans toutes les projections.
Tableau synthèse des impacts
| Catégorie | Impact principal | Exemple bancaire |
|---|---|---|
| Conception | Couplage fort | Event public exposant le modèle interne |
| Exploitation | Instabilité | Rebalances fréquents sur flux critiques |
| Données | Audit compromis | Compaction d’un topic transactionnel |
| Sécurité | Fuite PII | CDC sur tables métier sans filtrage |
| Observabilité | Diagnostic lent | Absence de correlation_id |
Ce tableau sert de rappel rapide lors des revues d’architecture. Il ne remplace pas une analyse détaillée, mais aide à prioriser les risques majeurs.
Plan de remédiation en trois étapes
1) Stabiliser le contrat: versionner les schémas, séparer commands et events, clarifier la clé de partition. Sans contrat stable, tout le reste est fragile. 2) Sécuriser l’exécution: rendre les consumers idempotents, introduire une outbox pour les writes critiques, et mettre en place une DLQ avec runbooks. 3) Rendre observable: dashboards, tracing, et alerting. La remédiation doit être mesurable; sinon, le risque réapparaît.
Dans une banque, ce plan doit être aligné avec la conformité et validé par les équipes métiers. Une correction technique isolée ne suffit pas si le processus opérationnel reste fragile.
Priorisation des risques
Tous les pièges n’ont pas le même impact. Une mauvaise clé de partition peut générer des incohérences immédiates, tandis qu’une gouvernance de schéma insuffisante produit des incidents plus tardifs mais tout aussi coûteux. En banque, la priorisation se fait souvent selon trois axes: impact client, impact réglementaire et coût de remédiation.
Une approche efficace consiste à traiter en priorité les flux financiers critiques (ledger, paiements, KYC), puis à étendre les bonnes pratiques aux flux secondaires (notifications, analytics). Cette hiérarchisation évite de disperser l’effort et permet d’obtenir rapidement un noyau robuste.
Cas d’étude bancaire: incident de virement instantané
Une banque lance un nouveau flux de virement instantané. Le producteur publie
TransferInitiated, le consumer ledger poste les écritures, puis un service
notifications informe le client. En production, un incident survient: certains
clients reçoivent deux notifications et le ledger affiche un solde incorrect.
Analyse post-mortem:
- La clé de partition était customer_id, ce qui a désordonné l’ordre des
mouvements d’un même compte.
- Le consumer ledger n’était pas idempotent, causant une double écriture.
- Le replay utilisé pour corriger le problème a renvoyé des notifications
réelles car aucun mode “dry-run” n’était prévu.
Correctifs:
- Partitionnement sur account_id.
- Déduplication par event_id dans le ledger.
- Isolation des effets externes via gateway désactivable.
Ce cas illustre comment plusieurs pièges peuvent se combiner et amplifier leurs effets. La correction n’est pas qu’un patch technique: elle exige une gouvernance, un replay contrôlé et des tests de résilience.
Signaux faibles à surveiller
Les incidents majeurs sont souvent précédés de signaux faibles: - augmentation du lag sans explication claire, - hausse progressive des retries côté producer, - croissance anormale des DLQ, - rebalances fréquents sur un consumer group.
Dans une banque, ces signaux doivent déclencher une investigation rapide, car ils indiquent souvent un problème structurel (partitioning, backpressure, schema drift) avant qu’un incident visible ne se produise.
Checklist de revue d’architecture
Avant de mettre un flux en production, il est utile de vérifier: - clé de partition alignée avec l’agrégat métier, - idempotence côté consumers, - compatibilité des schémas validée en CI, - stratégie de replay documentée, - observabilité (correlation_id, métriques, dashboards).
Cette checklist est particulièrement critique pour les flux bancaires soumis à audit. Elle réduit le risque de devoir corriger a posteriori un incident coûteux.
Stratégies de mitigation progressive
Lorsque plusieurs pièges sont identifiés, la correction doit être progressive. Quelques principes: - introduire l’outbox avant de modifier le schéma, - corriger l’idempotence avant d’activer les replays, - stabiliser les topics et le naming avant d’ajouter de nouveaux consumers.
En banque, ces changements doivent être coordonnés avec les équipes conformité et support. La mitigation n’est pas qu’une opération technique: elle engage la fiabilité opérationnelle et la confiance client.
Bonnes pratiques de base
- Documenter la clé de partition par domaine.
- Séparer commands et events.
prod.corebanking.transfer.cmd.initiate.v1prod.corebanking.transfer.evt.initiated.v1
- Versionner les schémas.
- Tester les replays sans effets externes.
Conclusion
Les pièges event-driven sont connus. La différence entre un système robuste et un système fragile est la discipline: partitioning correct, idempotence, schémas versionnés et observabilité. Dans une banque, cette discipline protège la cohérence comptable et la conformité. Elle réduit aussi le coût de maintenance et accélère l’évolution des produits sans compromettre la stabilité des flux financiers critiques. C’est un investissement durable pour la résilience bancaire. Les équipes qui internalisent ces pièges gagnent en vitesse de livraison et en confiance lors des audits. C’est aussi un vecteur de qualité durable.