CQRS (Command Query Responsibility Segregation)
Séparer le modèle qui accepte les commandes du modèle qui répond aux requêtes. Une séparation simple à formuler, structurante en production EDI.
Problème
Un hub EDI doit à la fois accepter les flux entrants (valider, dédupliquer, persister, accuser), et publier des vues à de multiples consommateurs (suivi de commande à l'exploitation, dashboard fournisseur, journal fiscal). Le même modèle relationnel optimisé pour l'écriture est presque toujours sous-optimal pour les requêtes — et inversement.
Forces
- Charges asymétriques. En EDI typique, les lectures sont 50 à 200× plus nombreuses que les écritures (consultations de tracking).
- Schémas divergents. La représentation idéale d'une commande pour l'audit fiscal n'est pas celle d'un dashboard KPI ni celle d'une API tracking.
- Cohérence temporelle acceptable. La plupart des vues métier tolèrent un lag de quelques secondes à minutes — la consistency forte sur le côté écriture suffit.
- Évolutivité indépendante. Read et write peuvent monter en charge séparément.
Solution
Le côté écriture (Command side) accepte les commandes (un message EDI entrant, une action ops), les valide, persiste l'état canonique et publie des événements de domaine. Le côté lecture (Query side) abonne un ou plusieurs projecteurs à ces événements et matérialise des modèles de lecture spécialisés. Les deux côtés peuvent utiliser des technologies différentes (PostgreSQL côté écriture, Elasticsearch côté lecture, Redis côté API tracking, Parquet côté lake fiscal).
Partenaires EDI ──► Command side ─► Event Store ─► Projecteurs ─► Read models
ORDERS (validate, (Kafka / (consumer) ┌── ERP table
INVOIC accept, EventStore) ├── KPI dashboard
DESADV reject) ├── Partner status API
└── Fiscal index
Implémentation EDI
Côté écriture, le hub reçoit un ORDERS, le valide (syntaxe, partenaire,
duplicate detection), persiste l'enveloppe + payload canonique en
table commands, et publie un événement OrderAccepted sur Kafka. Côté lecture, trois projecteurs
indépendants : erp-projector alimente la table SAP,
tracking-api-projector nourrit une API REST côté
fournisseur, fiscal-projector archive les éléments
requis pour la preuve 10 ans. Chaque projecteur peut être réindexé
sans impacter les autres ; un crash du projecteur fiscal n'arrête
pas les ORDERS entrants.
Anti-patterns
- CQRS sans Event Sourcing. Possible mais rare en pratique : sans journal d'événements, on perd la possibilité de reconstruire un read model défaillant.
- Cohérence forte read-after-write. Si le métier exige de voir immédiatement sa commande dans le dashboard, CQRS n'est pas adapté : privilégier un modèle unique.
- Trop de read models. Chaque projecteur a un coût d'exploitation. Un read model par concern, pas par écran.
- Read model écrit en direct. Si un acteur écrit simultanément dans le read model et le write model, on perd la cohérence du système.
Patterns liés
- Event Sourcing — partenaire naturel de CQRS.
- Modèle canonique — le format pivot du côté écriture.
- Outbox — la passerelle entre DB write et bus d'événements.
Sources
- Fowler M. — CQRS, martinfowler.com 2011. martinfowler.com/bliki/CQRS.html
- Young G. — CQRS Documents, 2010. cqrs_documents.pdf
- Microsoft Architecture Center — CQRS pattern. learn.microsoft.com/architecture/patterns/cqrs
- Kleppmann M. — Designing Data-Intensive Applications, O'Reilly 2017, chap. 12 « The Future of Data Systems ».