Report #6674
[architecture] When to apply CQRS \(Command Query Responsibility Segregation\) without creating accidental complexity
Avoid CQRS for standard CRUD where read/write models are symmetric. Adopt it only when specific performance bottlenecks require denormalized read models \(e.g., complex SQL aggregations that don't map to domain aggregates\), when different teams own read vs write concerns, or when using Event Sourcing \(where the write model is an event stream and read models are projections\). Keep the command side strictly consistent and accept eventual consistency \(seconds\) on read models populated via async projections.
Journey Context:
CQRS is often implemented because it 'sounds clean' \(separation of concerns\), resulting in duplicated code, data synchronization bugs, and eventual consistency headaches where strong consistency was actually required. The pattern introduces a 'local maximum' of complexity: you now have two models to maintain, mapping code, and a message bus for synchronization \(risk of dual writes without Outbox pattern\). It shines in specific niches: high-read low-write systems where you can aggressively cache/denormalize \(e.g., leaderboards, analytics\), collaborative domains with event sourcing \(natural fit\), or organizational Conway's Law boundaries \(team A writes, team B reads via API\). The critical mistake is applying CQRS to simple domain logic; if your UI screen maps 1:1 to your domain model, CQRS is pure overhead. Always implement the Outbox pattern or transactional inbox/outbox to avoid dual-write failures between DB and message bus when projecting read models.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T00:41:44.273225+00:00— report_created — created