CQRS (Command Query Responsibility Segregation) — L1/L2/L3 adoption, Event Sourcing, idempotency, integration with 5 DDD architectures.
When to Use This Skill
Trigger keywords: CQRS, read-write separation, Event Sourcing, event sourcing, Command Bus, Query Model, domain event, domain event, idempotency, idempotency, eventual consistency, projection, materialized view
Workflow
Step 1: 判断是否需要 CQRS → 确认读写模式是否显著分化
Step 2: 选择 CQRS 级别 → L1/L2/L3
Step 3: 设计命令模型 → Command → Handler → 领域事件
Step 4: 设计查询模型 → Query → Handler → DTO
Step 5: 实现事件同步(L2/L3)→ Outbox → 发布器 → 投影
Step 6: 按架构集成 → 根据 Layered/Onion/Hexagonal/Clean/COLA
When to Use CQRS
Applicable Scenarios
- Read and write patterns are significantly differentiated: Write operations and read operations use different data structures and optimization strategies
- High-concurrency writes: Writes require ACID guarantees, reads can accept eventual consistency
- Multi-view requirements: The same data has multiple presentation forms (list/detail/statistics/search)
- Audit trail requirements: Completely record the history of all state changes
- The team has event-driven capabilities: Understand the concepts of eventual consistency and event sourcing
Upgrade Path
CRUD 够用(读=写) → 单模型,无需 CQRS
↓
L1 模型分离 → CommandService / QueryService 分离,共享 DB
↓
L2 数据库分离 → Command DB + Query DB,事件同步
↓
L3 Event Sourcing → EventStore + Projection
Inapplicable Scenarios
| Scenario | Alternative |
|---|---|
| Simple CRUD, read = write | Single model, do not introduce CQRS |
| Prototype/one-off project | Skip CQRS |
| The team is unfamiliar with event-driven | First use ddd-event-storming to build event thinking |
| Extremely high strong consistency requirements | Evaluate the cost of distributed transactions |
CQRS Core Principles
| Dimension | Command Side (Write) | Query Side (Read) |
|---|---|---|
| Responsibility | Handle state changes, enforce business rules | Return data views, no business logic |
| Model | Command Model (command object + aggregate root) | Query Model (DTO + materialized view) |
| Storage | Write DB (3NF, ACID) | Read DB (denormalized, query-optimized) |
| Consistency | Strong consistency (within aggregate) | Eventual consistency (across aggregates/services) |
| Output | Domain event | DTO / View Model |
L1/L2/L3 Adoption Strategy
L1 — Model Separation
Lowest cost: only separate Command/Query Service at the code layer, sharing the database. Suitable for scenarios where the read and write data structures are the same but the logic is separated.
Reference example: examples/06-order-l1-model-separation.md
L2 — Database Separation
Medium cost: separate Command DB and Query DB, synchronized through domain events. Suitable for scenarios with high read load and the need for independent optimization strategies.
Reference example: examples/07-order-l2-db-separation.md
L3 — Event Sourcing
Highest cost: use the event stream as the single source of truth, and rebuild the read model through projections. Suitable for scenarios involving audit trails, time-travel queries, and event replay.
Reference example: examples/08-order-l3-event-sourcing.md
Event Lifecycle
领域行为 → 构建 DomainEvent → 持久化 → EventBus 发布
→ 本地处理器 (同步)
→ MQ 外发 (异步, 跨服务)
Publishing Strategy
- Polling publication (scheduled table scan): Latency 1-5s, low complexity, small to medium traffic
- CDC(Debezium binlog): Latency <100ms, medium complexity, high traffic and low latency
- Transaction commit callback: Latency <10ms, low complexity, Spring project
Detailed reference: references/02-cqrs-events.md
Idempotency Design
| Strategy | Overhead | Reliability | Scenario |
|---|---|---|---|
| Event deduplication table | Medium | ★★★ | Financial-grade critical events |
| State machine guard | Low | ★★★ | State-driven events |
| Redis + TTL | Low | ★★☆ | Non-critical notifications |
| Business idempotency | Low | ★★★ | Simple operations |
Detailed reference (including code examples): references/07-event-governance.md
CQRS Integration Patterns Across Architectures
| Architecture | Integration Point | Directory Structure |
|---|---|---|
| Layered | Application layer Command/Query Service separation | app/service/command/ + app/service/query/ |
| Onion | Core layer Command/Query UseCase interfaces | core/application/command/ + core/application/query/ |
| Hexagonal | Port layer Command Port + Query Port | domain/port/command/ + domain/port/query/ |
| Clean | UseCase layer Command Interactor + Query Interactor | usecase/interactor/command/ + usecase/interactor/query/ |
| COLA | App layer Command + Query submodules | app/command/ + app/query/ |
Detailed reference: examples/04-multi-architecture-integration.md
Gotchas
- Premature upgrade to L2/L3: First validate the value of CQRS at L1; L1 is sufficient for most projects
- Query side directly querying the write database: Query must never directly read the Command side database tables
- Forgetting event idempotency: Consumers must implement idempotency (at-least-once delivery)
- Event version incompatibility: Modifying event structures must be backward compatible
- UI handling of eventual consistency: Under L2/L3, the frontend needs polling or WebSocket
- Overly large aggregates: Event-sourced aggregates should follow the small aggregate principle
FAQ
| Question | Answer |
|---|---|
| Does CQRS necessarily introduce eventual consistency? | L1 does not require it; L2/L3 do |
| Is Event Sourcing bound to CQRS? | No, they can be used independently |
| When is the Outbox pattern needed? | When reliable event publishing is needed, to avoid the dual-write problem |
| What is the relationship between CQRS and microservices? | Orthogonal; can be deployed within a monolith or across microservices |
| How complex should the query model be? | Can be assembled across aggregates/services; denormalized materialized views |
Rules
| Rule | Description |
|---|---|
| Command side must verify permissions | Authorization is required before executing a command |
| Event payloads must not contain sensitive data | Passwords, PII, etc. should not appear in events |
| Query side must not modify state | Query Handlers/Services must not perform write operations |
| Write business data + Outbox in the same transaction | Avoid the dual-write problem |
| Strong consistency within an aggregate, eventual consistency between aggregates | A transaction may modify the state of at most one aggregate |
Skill Boundary
✅ Good at handling
- Systems with significantly divergent read/write patterns (reporting vs. transactions)
- Projects requiring an event-driven architecture
- Three-level progressive adoption of CQRS (L1 model separation / L2 DB separation / L3 Event Sourcing)
- Integration patterns with 5 DDD architectures
- Full lifecycle governance of domain events (publish/subscribe/idempotency/compensation)
⚠️ Requires conditions
- A base architecture has already been chosen (Layered/Onion/Hexagonal/Clean/COLA)
- The team understands eventual consistency and event-driven concepts
- The business scenario genuinely requires read/write separation (not simple CRUD)
❌ Should not be used (out of scope)
- Simple CRUD (read = write) → CQRS is not applicable
- Prototypes/one-off projects → CQRS should not be used
- Team unfamiliar with event-driven → First use
ddd-event-stormingto build event thinking - Already using a CQRS framework (Axon) → The framework has CQRS patterns built in
Security & Stability
- Code templates are educational — replace URLs/credentials with env vars.
- Command handlers must validate authorization. Never trust caller is authorized.
- Event payloads must not contain sensitive data — events are stored and replayed.
- Principle of least privilege: The Command API and Query API should use different access control permissions
Keywords
CQRS, 读写分离, Event Sourcing, 事件溯源, Command Bus, Query Model, Command Model, 领域事件, Domain Event, 最终一致性, Eventual Consistency, Outbox Pattern, Transactional Outbox, Materialized View, Projection, Event Store, Idempotency, 幂等, L1/L2/L3, Clean Architecture CQRS, Hexagonal CQRS, COLA CQRS
References
Architecture CQRS Patterns
references/architecture/01-clean-ddd-hexagonal-cqrs.md— CQRS & Domain Events:Commands, Queries, Read Models, Event Dispatcher, Outboxreferences/02-cqrs-events.md— CQRS domain events: event classification, event storage, projection strategy, version managementreferences/03-cqrs-mindmap.md— CQRS mind map: applicable scenarios, implementation strategiesreferences/04-ddd4j-cqrs-mindmap.md— CQRS mind map: core concepts, architectural patterns, components
Domain Events & Event Governance
references/07-event-governance.md— Event governance: Outbox DDL, idempotency, retry/dead letter/compensation/reconciliationreferences/domain-events/01-domain-events-deep.md— Domain events in depth: event-driven design principlesreferences/06-domain-vs-integration-events.md— Domain events vs integration events: boundary delineationreferences/08-partme-06-domain-events.md— Domain events in practice: insurance underwriting case
Examples
examples/06-order-l1-model-separation.md— Complete L1 model separation exampleexamples/07-order-l2-db-separation.md— L2 database separation + event synchronizationexamples/08-order-l3-event-sourcing.md— Complete L3 Event Sourcing exampleexamples/04-multi-architecture-integration.md— Comparison of CQRS integration across 5 architecturesexamples/03-inventory-cqrs.md— Inventory CQRS + idempotency strategy implementation