Chapter 1.2: When to Use EventCore
In the modern age of fast computers and cheap storage, event sourcing should be the default approach for any line-of-business application. This chapter explores why EventCore is the right choice for your next project and addresses common concerns.
Why Event Sourcing Should Be Your Default
Traditional CRUD databases were designed in an era of expensive storage and slow computers. They optimize for storage efficiency by throwing away history - a terrible trade-off in today’s world. Here’s why event sourcing, and specifically EventCore, should be your default choice:
1. History is Free
Storage costs have plummeted. The complete history of your business operations costs pennies to store but provides immense value:
- Debug production issues by replaying events
- Satisfy any future audit requirement
- Build new features on historical data
- Prove compliance retroactively
2. CRUD Lies About Your Business
CRUD operations (Create, Read, Update, Delete) are technical concepts that don’t match business reality:
- “Update” erases the reason for change
- “Delete” pretends things never existed
- State-based models lose critical business context
Event sourcing captures what actually happened: “CustomerChangedAddress”, “OrderCancelled”, “PriceAdjusted”
3. Future-Proof by Default
With EventCore, you never have to say “we didn’t track that”:
- New reporting requirements? Replay events into new projections
- Need to add analytics? The data is already there
- Compliance rules changed? Full history available
EventCore Makes Event Sourcing Practical
While event sourcing should be the default, EventCore specifically excels by solving traditional event sourcing pain points:
1. Complex Business Transactions
Problem: Your business operations span multiple entities that must change together.
Example: E-commerce order fulfillment
#![allow(unused)] fn main() { #[derive(Command, Clone)] struct FulfillOrder { #[stream] order: StreamId, // Update order status #[stream] inventory: StreamId, // Deduct items #[stream] shipping: StreamId, // Create shipping record #[stream] customer: StreamId, // Update loyalty points } }
Why EventCore: Traditional systems require distributed transactions or eventual consistency. EventCore makes this atomic and simple.
2. Financial Systems
Problem: Need complete audit trail and strong consistency for money movements.
Example: Payment processing
#![allow(unused)] fn main() { #[derive(Command, Clone)] struct ProcessPayment { #[stream] customer_account: StreamId, #[stream] merchant_account: StreamId, #[stream] payment_gateway: StreamId, #[stream] tax_authority: StreamId, } }
Why EventCore:
- Every state change is recorded
- Natural audit log for compliance
- Atomic operations prevent partial payments
- Easy to replay for reconciliation
3. Collaborative Systems
Problem: Multiple users modifying shared resources with conflict resolution needs.
Example: Project management tool
#![allow(unused)] fn main() { #[derive(Command, Clone)] struct MoveTaskToColumn { #[stream] task: StreamId, #[stream] from_column: StreamId, #[stream] to_column: StreamId, #[stream] project: StreamId, } }
Why EventCore:
- Event streams enable real-time updates
- Natural conflict resolution through events
- Complete history of who did what when
4. Regulatory Compliance
Problem: Regulations require you to show complete history of data changes.
Example: Healthcare records
#![allow(unused)] fn main() { #[derive(Command, Clone)] struct UpdatePatientRecord { #[stream] patient: StreamId, #[stream] physician: StreamId, #[stream] audit_log: StreamId, } }
Why EventCore:
- Immutable event log satisfies auditors
- Can prove system state at any point in time
- Natural GDPR compliance (event-level data retention)
5. Domain-Driven Design
Problem: Your domain has complex rules that span multiple aggregates.
Example: Insurance claim processing
#![allow(unused)] fn main() { #[derive(Command, Clone)] struct ProcessClaim { #[stream] claim: StreamId, #[stream] policy: StreamId, #[stream] customer: StreamId, #[stream] adjuster: StreamId, } }
Why EventCore:
- Commands match business operations exactly
- No artificial aggregate boundaries
- Domain events become first-class citizens
Addressing Common Concerns
“But Event Sourcing is Complex!”
Myth: Event sourcing adds unnecessary complexity.
Reality: EventCore makes it simpler than CRUD:
- No O/R mapping impedance mismatch
- Commands map directly to business operations
- No “load-modify-save” race conditions
- Debugging is easier with full history
“What About Performance?”
Myth: Event sourcing is slow because it stores everything.
Reality:
- EventCore achieves ~83 ops/sec with PostgreSQL - plenty for most business applications
- Read models can be optimized for any query pattern
- No complex joins needed - data is pre-projected
- Scales horizontally by splitting streams
“Storage Costs Will Explode!”
Myth: Storing all events is expensive.
Reality: Let’s do the math:
- Average event size: ~1KB
- 1000 events/day = 365K events/year = 365MB/year
- S3 storage cost: ~$0.023/GB/month = $0.10/year
- Your complete business history costs less than a coffee
“What About GDPR/Privacy?”
Myth: You can’t delete data with event sourcing.
Reality: EventCore provides better privacy controls:
- Crypto-shredding: Delete encryption keys to make data unreadable
- Event-level retention policies
- Selective projection rebuilding
- Actually know what data you have about someone
Special Considerations
Large Binary Data
For systems with large binary data (images, videos), use a hybrid approach:
- Store metadata and operations as events
- Store binaries in object storage (S3)
- Best of both worlds
Graph-Heavy Queries
For social networks or recommendation engines:
- Use EventCore for the write side
- Project into graph databases for queries
- Maintain consistency through event streams
Cache-Like Workloads
For session storage or caching:
- These aren’t business operations
- Use appropriate tools (Redis)
- EventCore for business logic, Redis for caching
Migration Considerations
From Traditional Database
Good fit if:
- You need better audit trails
- Business rules span multiple tables
- You’re already using event-driven architecture
Poor fit if:
- Current solution works well
- No complex business rules
- Just need basic CRUD
From Microservices
Good fit if:
- Struggling with distributed transactions
- Need better consistency guarantees
- Want to simplify architecture
Poor fit if:
- True service isolation is required
- Different teams own different services
- Services use different tech stacks
Performance Considerations
EventCore is optimized for:
- ✅ Correctness and consistency
- ✅ Complex business operations
- ✅ Audit and compliance needs
EventCore is NOT optimized for:
- ❌ Maximum throughput (~83 ops/sec with PostgreSQL)
- ❌ Minimum latency (ms-level operations)
- ❌ Large binary data
The Right Question
Instead of asking “Do I need event sourcing?”, ask:
“Can I afford to throw away my business history?”
In an era of:
- Regulatory scrutiny
- Data-driven decisions
- Machine learning opportunities
- Debugging production issues
- Changing business requirements
The answer is almost always NO.
Decision Framework
Start with EventCore for:
- ✅ Any line-of-business application - Your default choice
- ✅ Multi-entity operations - EventCore’s sweet spot
- ✅ Financial systems - Audit trail included
- ✅ Collaborative tools - Natural conflict resolution
- ✅ Regulated industries - Compliance built-in
- ✅ Domain-driven design - Commands match your domain
Consider Alternatives Only For:
- 🤔 Pure caching layers - Use Redis alongside EventCore
- 🤔 Binary blob storage - Hybrid approach with S3
- 🤔 >1000 ops/sec - Add caching or consider specialized solutions
Summary
In 2024 and beyond, the question isn’t “Why event sourcing?” but “Why would you throw away your business history?”
EventCore makes event sourcing practical by:
- Eliminating aggregate boundary problems
- Providing multi-stream atomicity
- Making it type-safe and simple
- Scaling to real business needs
Storage is cheap. History is valuable. Make event sourcing your default.
Ready to dive deeper? Let’s explore Event Modeling Fundamentals →