CQRS (Command Query Responsibility Segregation)
Separate the model that accepts commands from the model that answers queries. A simple separation to state, structuring in EDI production.
Problem
An EDI hub must both accept inbound flows (validate, deduplicate, persist, ack), and publish views to many consumers (order tracking for operations, supplier dashboard, fiscal journal). The same relational model optimised for writes is almost always suboptimal for queries — and vice versa.
Forces
- Asymmetric loads. In a typical EDI hub, reads are 50× to 200× more numerous than writes (tracking lookups).
- Divergent schemas. The ideal shape of an order for fiscal audit is not the one for a KPI dashboard nor for a tracking API.
- Acceptable temporal consistency. Most business views tolerate a few seconds to minutes of lag — strong consistency on the write side is enough.
- Independent scalability. Read and write can scale separately.
Solution
The write side (Command side) accepts commands (an inbound EDI message, an ops action), validates, persists the canonical state and publishes domain events. The read side (Query side) subscribes one or more projectors to those events and materialises specialised read models. The two sides may use different technologies (PostgreSQL on the write side, Elasticsearch on the read side, Redis for the tracking API, Parquet for the fiscal lake).
EDI partners ──► Command side ─► Event Store ─► Projectors ─► Read models
ORDERS (validate, (Kafka / (consumer) ┌── ERP table
INVOIC accept, EventStore) ├── KPI dashboard
DESADV reject) ├── Partner status API
└── Fiscal index
EDI implementation
On the write side, the hub receives an ORDERS, validates it (syntax,
partner, duplicate detection), persists the envelope + canonical
payload in a commands table, and publishes an OrderAccepted event to Kafka. On the read side, three
independent projectors: erp-projector feeds the SAP
table, tracking-api-projector feeds a REST API for the
supplier, fiscal-projector archives the elements
required for the 10-year proof. Each projector can be reindexed
without impacting the others; a crash of the fiscal projector does
not stop inbound ORDERS.
Anti-patterns
- CQRS without Event Sourcing. Possible but rare in practice: without an event journal, a failing read model cannot be rebuilt.
- Strong read-after-write consistency. If the business requires immediate visibility of an order in the dashboard, CQRS is not the right fit: prefer a single model.
- Too many read models. Each projector has an operational cost. One read model per concern, not per screen.
- Read model written directly. If an actor writes simultaneously to the read model and the write model, system consistency is lost.
Related patterns
- Event Sourcing — CQRS's natural partner.
- Canonical Model — the pivot format on the write side.
- Outbox — the bridge between DB write and event bus.
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".