CQRS pattern for Dynamics 365
How CQRS (Command Query Responsibility Segregation) applies to Dynamics 365 architectures — write vs read separation, projection patterns, and when CQRS helps vs hurts.
Command Query Responsibility Segregation (CQRS) separates write operations (commands) from read operations (queries). For complex domains with imbalanced read/write loads or different consistency needs, this separation enables independent optimisation. Some Dynamics 365 architectures benefit from CQRS principles, particularly for high-volume read scenarios.
The core idea.
- Command — change state (Create, Update, Delete).
- Query — read state.
- Separate models for each.
- Read model projected from write model.
The separation enables specialisation; read-optimised vs write-optimised.
Why separate.
- Different scale needs — reads typically more numerous than writes.
- Different schemas — denormalised reads, normalised writes.
- Different consistency — eventual consistency for reads acceptable.
- Different security — read access broader than write.
The asymmetry is fundamental; CQRS exposes it as architecture.
In Dynamics 365 context.
- Write side — Dataverse / F&O — the system of record.
- Read side — replicated to optimised store.
- Projection — translates write events to read updates.
Examples:
- Dataverse + Power BI semantic model — semantic model is read-optimised projection.
- F&O + data lake — lake is read-optimised projection.
- Dataverse + Azure Search — search index is read-optimised.
Where CQRS clearly helps.
- Analytical workloads — heavy reads, infrequent writes; warehouse pattern.
- Search workloads — search index optimised for queries.
- Reporting — read-only views without taxing operational system.
- Customer-facing portals — high read volume from many users.
- Cross-system aggregation — combine sources into queryable view.
Where CQRS adds unnecessary complexity.
- Simple CRUD — no benefit from separation.
- Tight consistency requirements — eventual consistency unacceptable.
- Low scale — overhead exceeds benefit.
CQRS isn't universally appropriate; assess fit.
Projection mechanisms.
- Synapse Link / Fabric Link — Dataverse / F&O to lake.
- Power BI semantic models — Dataverse to BI.
- Custom replication — for specific destinations.
- Cosmos DB Change Feed + processor — for high-throughput scenarios.
Each has trade-offs in latency, consistency, cost.
Eventual consistency. A defining characteristic:
- Write to source.
- Projection happens asynchronously.
- Read sees updated value some time later.
For most analytics, seconds-to-minutes lag is fine. For real-time requirements, less so.
Write-side model.
- Optimised for transactional integrity.
- Normalised schema.
- Strong consistency.
- Business logic enforced.
This is Dataverse / F&O standard model.
Read-side model.
- Optimised for query patterns.
- Denormalised structure.
- Pre-computed aggregations.
- Multiple representations (per user role, per use case).
Often columnar storage; star schema; materialised views.
Multiple read models. From one write source:
- Operational read — recent transactions.
- Analytical read — historical aggregates.
- Search read — text-searchable.
- Geo read — spatial queries.
Each tuned to its purpose.
Updates and consistency.
- Strict consistency — read sees write immediately. Hard distributed.
- Eventual consistency — read sees write eventually.
- Read-your-own-writes — user sees their own changes.
- Causal consistency — if A caused B, B not seen before A.
Most CQRS systems offer eventual; design around it.
Conflict handling.
- Multiple writers; same data updated.
- Write side handles via optimistic concurrency or pessimistic locks.
- Projection handles via "last write wins" or merge logic.
Cross-system updates particularly vulnerable; saga patterns help.
Event sourcing + CQRS. Often combined:
- Events as the source of truth (event sourcing).
- Projections build query models from events.
- Replay rebuilds projections.
Powerful but heavy; reserved for specific scenarios.
Dynamics 365 + Fabric pattern. Modern example:
- Dataverse and F&O are write-side.
- Fabric Lakehouse / Warehouse are read-side.
- Synapse / Fabric Link provides projection.
- Power BI queries Fabric.
This is CQRS in practice; standard architecture for analytics.
Cache as read model. Simpler form:
- Frequently-queried Dataverse data cached.
- Cache invalidated on changes.
- Reads hit cache; writes go to source.
Lightweight CQRS for specific scenarios.
Common pitfalls.
- Over-engineering. CQRS where simpler approach sufficed.
- No clear projection strategy. Read side built ad-hoc.
- Consistency assumptions wrong. Code assumes strict; gets eventual.
- Projection lag too long. Reads stale beyond tolerance.
- Schema drift. Write and read models diverge.
- No monitoring of projection health. Lag invisible until users complain.
Best practices.
- Use case-driven. Apply CQRS where pattern fits, not because it's fashionable.
- Define consistency model. Be explicit about read freshness.
- Schema discipline in both models.
- Monitor projection latency.
- Recovery / rebuild capability — rebuild read from write if needed.
Performance implications.
- Write performance — slightly slower due to projection trigger.
- Read performance — significantly faster, well-tuned.
- Storage cost — duplicated data.
Net positive for read-heavy workloads; may be net negative for write-heavy.
Operational implications.
- More moving parts — more to monitor.
- More dependencies — projection can fail.
- More expertise needed — more patterns to understand.
Operational cost real; weigh against benefit.
Strategic positioning. CQRS is a powerful pattern for the right problem. Dynamics 365 implementations regularly use CQRS principles without naming it — Synapse Link, semantic models, search indexes are all read-side projections. Naming the pattern enables intentional design.
For architects:
- Recognise CQRS opportunities (read-heavy, multi-consumer patterns).
- Choose appropriate projection technology.
- Define consistency expectations.
- Plan operational support.
For greenfield analytics or customer-facing query workloads, CQRS principles produce better architectures. For simple operational systems, traditional CRUD remains right. Match pattern to problem.
Related guides
- The outbox pattern with Service BusA resilient integration pattern for Dynamics 365 — combining an outbox table with Service Bus to deliver guaranteed-once messaging across systems.
- The saga pattern for cross-system Dynamics 365 transactionsHow to handle multi-system business transactions that need to be atomic across Dynamics 365 and external systems — orchestration vs choreography, compensation, and the implementation patterns.
- Anti-corruption layers for Dynamics 365 integrationsHow anti-corruption layers protect Dynamics 365 from external system model leakage — translation patterns, when to apply ACL, and the maintenance discipline.
- API Gateway patterns for Dynamics 365How API gateways enhance Dynamics 365 integration architecture — Azure API Management, security, rate limiting, transformation, and the patterns for managed API surfaces.
- Event-driven architecture for Dynamics 365How to design event-driven integrations around Dynamics 365 — event sources, brokers, consumers, and the patterns that produce loosely coupled, scalable architectures.