Event Sourcing FAQ
"We achieved everything from DDD without doing DDD" - Adam Dymitruk
On this page, we answer the most important questions about Event Sourcing. Best of all, you can submit your own questions and they will be published here (anonymously if you wish).
Common Questions
What is CQRS and does it necessarily belong with Event Sourcing?
CQRS (Command Query Responsibility Segregation) is a pattern that separates read and write operations in a system. While CQRS and Event Sourcing work exceptionally well together, they are independent patterns. You can use Event Sourcing without CQRS, and you can use CQRS without Event Sourcing.
However, Event Sourcing naturally leads to CQRS because:
- Events form the single source of truth (write side)
- Read models are built from events (read side)
- This separation enables optimized queries without compromising write integrity
How does Event versioning work?
Event versioning is about handling schema evolution in your event store. There are several approaches:
- Upcasting: Transform old event versions to new versions when reading
- Multiple Handlers: Support multiple event versions in your code
- Copy & Transform: Create migration processes to transform old events
- Weak Schema: Use flexible event structures that can evolve
The key is to never modify historical events - they represent immutable facts that occurred in the past.
How large should events be?
Events should contain all information needed to represent a meaningful business fact. The size isn’t as important as the semantic meaning:
- Too small: “FieldChanged” events make it hard to understand business intent
- Too large: Bundling unrelated changes makes events hard to consume
- Just right: “OrderPlaced” with all relevant order details
Think in terms of business meaning, not technical size constraints. An event represents something that happened - make sure it tells that story completely.
How performant is Event Sourcing?
Event Sourcing is highly performant when implemented correctly:
Writes: Append-only writes are extremely fast (no updates or deletes) Reads: Read models can be optimized for specific queries Scalability: Event stores scale horizontally very well
Common performance optimizations:
- Use snapshots to avoid replaying thousands of events
- Cache read models
- Use eventual consistency where real-time isn’t needed
How do you generate sequences in Event Sourcing?
Sequences (like order numbers) can be handled in several ways:
- Natural IDs: Use business-meaningful identifiers (email, account number)
- UUIDs: Generate globally unique identifiers
- Reservation Pattern: Reserve a sequence number as part of your command
- Dedicated Aggregate: Create a sequence generator aggregate
The reservation pattern works well for user-visible sequences: reserve the number first, then use it in your command.
How do you delete in Event Sourcing?
You don’t delete events - you model deletion as a business event:
- Soft Delete: Emit an “AccountClosed” or “OrderCancelled” event
- GDPR Compliance: Use encryption and delete the key, or use specific tombstone events
- Projections: Update read models to reflect deletion
Remember: deletion is a business action that happened at a point in time. Capture that fact as an event.
What are Passive-Aggressive Events?
Passive-Aggressive Events are events named as commands rather than facts:
- Passive-Aggressive: “CreateUser”, “UpdateOrder”, “DeleteAccount”
- Proper Events: “UserCreated”, “OrderUpdated”, “AccountDeleted”
Events should be in past tense and describe what happened, not what should happen. This distinction is crucial for understanding event-driven systems.
How do you implement unique constraints with Event Sourcing? Reservation Pattern?
Unique constraints require coordination. Common approaches:
- Reservation Pattern:
- Reserve the unique value before using it
- If reservation succeeds, proceed with the operation
- If it fails, reject the command
- Aggregate Design:
- Make the unique value the aggregate ID
- Natural uniqueness through ID constraints
- Eventually Consistent Check:
- Allow duplicates temporarily
- Detect and resolve them asynchronously
The reservation pattern is most common: treat the unique constraint as a resource that must be reserved.
Is there recommended literature?
Yes, here are some essential resources:
- Versioning in an Event Sourced System by Greg Young
- The Event Sourcing Book - Comprehensive guide to Event Sourcing and Event Modeling
- Event Sourcing Patterns - Community resources and patterns
Check out our blog for practical articles on Event Sourcing implementation.
Want to learn more?
Explore our Event Modeling Toolkit or check out The Event Sourcing Book.