CQRS with Protean
Builds on DDD
This approach adds Commands, Command Handlers, and Projections on top of the DDD foundation. If you haven't read the DDD pathway yet, start there — CQRS extends those concepts.
Overview
CQRS (Command Query Responsibility Segregation) separates your application into a write side and a read side. On the write side, explicit Commands capture user intent and Command Handlers orchestrate aggregate changes. On the read side, Projections provide query-optimized views built from domain events.
This replaces Application Services with a more structured pattern: instead
of calling methods directly, the API layer submits Commands via
domain.process(), and Command Handlers execute the business logic. Events
flow to Projectors that maintain read models optimized for each query need.
Request Flow
sequenceDiagram
autonumber
participant API as API Layer
participant D as domain.process()
participant CH as Command Handler
participant R as Repository
participant Agg as Aggregate
participant EH as Event Handler
participant P as Projector
participant Proj as Projection
API->>D: Submit Command
D->>CH: Dispatch to handler
CH->>R: Load aggregate
R-->>CH: Aggregate
CH->>Agg: Invoke domain method
Agg->>Agg: Mutate state, raise event
CH->>R: Persist aggregate
R-->>EH: Domain event dispatched
EH->>EH: Handle side effects
R-->>P: Domain event dispatched
P->>Proj: Update read model
- The API layer creates a Command and submits it via
domain.process() - The framework dispatches the command to the appropriate Command Handler
- The handler loads the aggregate from the Repository
- It invokes the domain method on the aggregate
- The aggregate mutates state and raises events
- The handler persists the aggregate
- Events flow to Event Handlers for side effects and to Projectors that update read-optimized Projections
What CQRS Adds to DDD
| DDD Element | CQRS Replacement/Addition |
|---|---|
| Application Services | Commands + Command Handlers replace direct method calls |
| — | Projections provide dedicated read models |
| — | Projectors build projections from events |
| Events + Event Handlers | Same as DDD, but now also feed projectors |
| Repositories | Same as DDD |
Elements You'll Use
Everything from the DDD pathway, plus:
| Element | Purpose |
|---|---|
| Commands | Immutable DTOs representing intent to change state |
| Command Handlers | Process commands and orchestrate aggregate changes |
| Projections | Read-optimized views stored in database or cache |
| Subscribers | Consume messages from external message brokers |
| Server | Async processing engine for events and commands |
Guided Reading Order
If you've already worked through the DDD pathway, pick up from step 4. Otherwise, start from the beginning:
| Step | Guide | What You'll Learn |
|---|---|---|
| 1 | Compose a Domain | Register elements, initialize and activate your domain |
| 2 | Define Concepts | Aggregates, entities, value objects, fields |
| 3 | Add Behavior | Validations, invariants, mutations, raising events |
| 4 | Commands | Define commands that capture user intent |
| 5 | Command Handlers | Process commands and coordinate aggregates |
| 6 | Persist Aggregates | Save and load aggregates via repositories |
| 7 | Events | Define domain events |
| 8 | Event Handlers | React to events for side effects and cross-aggregate sync |
| 9 | Projections | Build read-optimized views from events |
| 10 | Server | Run the async processing engine |
| 11 | Configuration | Configure databases, brokers, and event stores |
| 12 | Testing | Test commands, handlers, and projections |
When to Evolve to Event Sourcing
Consider moving to Event Sourcing when an aggregate meets two or more of these criteria:
- Strong auditability required — regulatory compliance or financial transactions requiring complete traceability
- Temporal analysis needed — historical reporting or state reconstruction at any point in time
- Complex state transitions — multi-step workflows with intricate business rules
- Event-driven integration — other bounded contexts consume your events as their primary data source
Note
You don't have to move your entire domain to Event Sourcing. Protean supports mixing CQRS and Event Sourcing at the aggregate level within the same domain. See the Architecture Decision guide for the full decision framework.