Event Sourcing stores state changes as a sequence of events. CQRS separates read and write operations. Together, they enable powerful patterns for complex systems.
What is Event Sourcing?#
Traditional State Storage#
Traditional approach:
┌─────────────────────────────────┐
│ Account │
│ ───────── │
│ id: acc_123 │
│ balance: $500 │
│ status: active │
└─────────────────────────────────┘
Question: How did we get to $500?
Answer: Unknown 🤷
Event Sourcing Approach#
Event sourcing approach:
┌─────────────────────────────────┐
│ Events for acc_123 │
│ ───────────────── │
│ 1. AccountOpened($0) │
│ 2. MoneyDeposited($1000) │
│ 3. MoneyWithdrawn($300) │
│ 4. MoneyWithdrawn($200) │
└─────────────────────────────────┘
Current state: $1000 - $300 - $200 = $500
Full history available ✓
Implementing Event Sourcing#
Event Store#
Aggregate with Events#
Repository#
CQRS (Command Query Responsibility Segregation)#
The Problem#
Without CQRS:
┌─────────────────────────────────────┐
│ Same model for reads and writes │
│ ───────────────────────────────── │
│ - Write optimized for consistency │
│ - Read needs denormalized data │
│ - Conflicts in design decisions │
└─────────────────────────────────────┘
CQRS Solution#
With CQRS:
┌─────────────────┐ ┌─────────────────┐
│ Write Model │ │ Read Model │
│ ───────────── │ │ ───────────── │
│ - Commands │ │ - Queries │
│ - Aggregates │ │ - Projections │
│ - Consistency │ │ - Optimized │
└────────┬────────┘ └────────▲────────┘
│ │
│ ┌─────────┐ │
└────▶│ Events │───────┘
└─────────┘
Write Side#
Read Side (Projections)#
Snapshots#
Benefits and Trade-offs#
Benefits#
✓ Complete audit trail
✓ Time travel (rebuild state at any point)
✓ Event replay for debugging
✓ Separate read/write optimization
✓ Scalable read models
✓ Easy to add new projections
Trade-offs#
✗ Increased complexity
✗ Eventual consistency between read/write
✗ Event schema evolution challenges
✗ More infrastructure (event store, projections)
✗ Learning curve
When to Use#
Good fit:
- Audit requirements
- Complex domain with many state transitions
- Need for multiple read models
- High read/write ratio
Not ideal:
- Simple CRUD applications
- Strong consistency requirements
- Small teams without event sourcing experience
Conclusion#
Event sourcing and CQRS are powerful patterns for complex domains. They provide complete audit trails, enable flexible read models, and support scalable architectures.
Start simple: event sourcing alone adds significant value. Add CQRS when you need optimized read models. The patterns work best together but aren't required to be used together.