Day 021: Event Sourcing - Events as the Source of Truth
Topic: Event sourcing fundamentals
π‘ Today's "Aha!" Moment
The insight: Traditional databases store current state ("balance: $100"). Event Sourcing stores history of changes ("created account, deposited $50, deposited $50"). Current state becomes derived dataβreplay events to reconstruct it.
Why this matters:
Most systems throw away history. When you UPDATE a database row, the old value vanishes forever. Questions become impossible to answer:
- "What was the balance last Tuesday at 3 PM?" β Gone
- "Who approved this transaction?" β No record
- "Why did the price change?" β No audit trail
Event Sourcing keeps everything. Every change is an immutable event:
Events (append-only):
1. AccountCreated { id: 123, owner: "Alice", timestamp: "2024-01-01T10:00:00Z" }
2. MoneyDeposited { id: 123, amount: 50, timestamp: "2024-01-02T14:30:00Z" }
3. MoneyWithdrawn { id: 123, amount: 20, timestamp: "2024-01-03T09:15:00Z" }
Current State (derived by replaying events 1β2β3):
balance = 0 + 50 - 20 = $30
Want state at any moment? Replay events up to that timestamp. Need audit trail? Events ARE the audit trail. Bug in business logic? Fix code, replay events, correct state.
The pattern: Store facts (events), derive state (projections)
This pattern appears wherever history matters more than current state:
- Version control (Git): Commits are events, current code is derived (checkout = replay)
- Accounting ledgers: Transactions are immutable, balance is calculated
- Blockchain: Blocks are events, balances derived by scanning chain
- Apache Kafka: Topics store events, consumers derive views
π Why This Matters
Event Sourcing revolutionizes system design by providing perfect audit trails, time travel debugging, and unmatched data integrity. Major companies like Amazon, Netflix, and financial institutions rely on this pattern for critical systems.
π― Daily Objective
Master the Event Sourcing pattern: understand how storing events instead of state revolutionizes system design, enables time travel debugging, and provides perfect audit trails. Build a practical event-sourced system from scratch.
π Topics Covered
- Banking: Transactions logged forever, balance recalculated from ledger
How to recognize Event Sourcing fits:
| Use Event Sourcing when: | Avoid Event Sourcing when: |
|---|---|
| Audit trail is legally required | Simple CRUD, history irrelevant |
| Time travel debugging needed | Performance-critical reads (millions/sec) |
| Complex business logic prone to bugs | Small app, no regulatory requirements |
| Multiple projections from same events | Team unfamiliar with pattern |
| Temporal queries ("state at time T") | Data never changes (append-only anyway) |
Common misconceptions:
β Myth: "Event Sourcing means no database"
β
Truth: Events are stored in a database (event store). It's append-only database, not stateless.
β Myth: "Event Sourcing is always paired with CQRS"
β
Truth: They complement each other but are independent. Can use Event Sourcing without CQRS (single model).
β Myth: "Replay is too slow for production"
β
Truth: Use snapshotsβsave state every N events, replay from latest snapshot. Example: Snapshot every 100 events, replay 10-20 events = milliseconds.
Real-world examples:
-
Banking systems: Every transaction is event (deposit, withdrawal, transfer). Balance derived from transaction history. Regulation requires keeping transactions forever.
-
GitHub commit history: Each commit is immutable event. Current repo state = replay all commits. Time travel via
git checkout <commit>. -
Apache Kafka: Log-based architecture. Topics store events forever (or until retention), consumers replay to rebuild state.
-
Event Store DB: Purpose-built database for Event Sourcing (created by Greg Young). Optimized for append-only writes, fast event replay.
-
AWS EventBridge: Event-driven architecture. Services publish events, other services subscribe. Events stored for replay.
-
Airline booking: Reservation events (SeatReserved, PaymentReceived, TicketIssued). Can reconstruct exact booking flow, handle disputes.
What changes after this realization:
You stop thinking "CRUD" (Create, Read, Update, Delete). You start thinking "What happened?" instead of "What is?"
- Traditional:
UPDATE users SET balance = 100(loses history) - Event Sourcing:
APPEND UserBalanceChanged { delta: +50 }(keeps history)
You recognize events as first-class citizens:
- Events document business processes (domain language)
- Events enable new features without touching old code (add projection)
- Events provide built-in audit trail (compliance for free)
You understand trade-offs:
- Pros: Perfect audit, time travel, bug correction by replay, new views without migration
- Cons: Complexity, eventual consistency, storage grows (mitigated by snapshots), schema evolution
You learn event schema design:
// β Bad event (imperative, no context)
{ type: "UPDATE", field: "balance", value: 100 }
// β
Good event (declarative, business meaningful)
{
type: "MoneyDeposited",
accountId: "123",
amount: 50,
depositedBy: "ATM_456",
timestamp: "2024-01-02T14:30:00Z",
reason: "Salary payment"
}
Good events are:
- Past tense (MoneyDeposited, not DepositMoney)
- Business meaningful (not technical)
- Immutable (never modified after creation)
- Self-contained (all info to process)
Meta-insight:
Event Sourcing inverts database philosophy. Traditional DB: State is truth, changes are side effects. Event Sourcing: Changes are truth, state is side effect.
This mirrors how humans think about stories:
- We remember what happened (events), not static snapshots
- History is told through sequences of events (World War II events, not "Europe in 1945")
- Legal systems record actions (contracts, court decisions), not current state
The deepest lesson: Time is fundamental to reality. Physics records events (spacetime), not states. Causality flows through events. Event Sourcing acknowledges that systems exist in timeβevery state has a history, every decision has a cause.
By storing the timeline instead of a snapshot, we preserve the truth about what actually happened. Current state is an opinion (derived from events). Events are facts.
π Detailed Curriculum (Optimized for 60 min)
-
Video Introduction (15 min) β START HERE
-
Greg Young: "Event Sourcing" (CQRS/DDD Europe)
- Video Link
-
Core concepts and motivation
-
Core Reading (15 min)
-
Martin Fowler: "Event Sourcing"
- Article
-
Focus: Pattern description, benefits, and when to use
-
Quick Synthesis (5 min)
- Write: "Event Sourcing in 3 key ideas"
- Draw simple event store diagram
- Note biggest insight
π Resources
π― Core Resources (Use Today)
- Video: Greg Young - Event Sourcing
- Introduction to Event Sourcing (15 min watch)
- Why watch: Greg Young invented modern Event Sourcing patterns. This talk provides foundational understanding from the source.
- Article: Martin Fowler - Event Sourcing pattern
- Event Sourcing pattern explained
- Focus: Core concepts, when to use, and common pitfalls from architecture authority.
- Tutorial: EventStore documentation basics
- EventStoreDB Getting Started
- Practical value: Hands-on tutorial with purpose-built event sourcing database.
β Bonus Resources (If Extra Time)
- Book: "Versioning in an Event Sourced System" - Greg Young
- Free PDF
- Advanced topic: How to evolve event schemas without breaking existing systems.
- Article: "Event Sourcing: What it is and why it's awesome" - Confluent
- Confluent blog
- Use case: Event sourcing with Apache Kafka for scalable systems.
- Video: "Event Sourcing: You are doing it wrong" - David Schmitz
- Common mistakes talk
- Learn from failures: Avoid typical implementation pitfalls.
- Deep Dive: CQRS Journey - Microsoft patterns & practices
- Microsoft CQRS documentation
- Enterprise patterns: Production-ready Event Sourcing + CQRS implementation guide.
βοΈ Practical Activities (25 min total)
1. Build Simple Event Store (15 min)
Implement a basic event-sourced bank account in pseudocode/your language:
// Events
AccountCreated { accountId, ownerId, timestamp }
MoneyDeposited { accountId, amount, timestamp }
MoneyWithdrawn { accountId, amount, timestamp }
// Event Store
class EventStore {
events = []
append(event) {
events.push(event)
}
getEvents(accountId) {
return events.filter(e => e.accountId == accountId)
}
}
// Account (reconstructed from events)
class Account {
id, balance = 0
static fromEvents(events) {
account = new Account()
for event in events {
account.apply(event)
}
return account
}
apply(event) {
match event {
AccountCreated => this.id = event.accountId
MoneyDeposited => this.balance += event.amount
MoneyWithdrawn => this.balance -= event.amount
}
}
}
Tasks:
- Implement the event store
- Create events for: create account, deposit $100, withdraw $50
- Reconstruct account state from events
- Add console output showing event history
2. Event Diagram (7 min)
Draw a sequence diagram showing:
User β Command β Event Store β Event β Read Model
β
Event 1, 2, 3...
β
Replay β Current State
3. Reflection (3 min)
Answer:
- How is this different from traditional CRUD?
- What problems does event sourcing solve?
- When would you NOT use event sourcing?
π¨ Creativity - Quick Mental Reset (5 min)
Quick Exercise: "The Event Timeline"
Draw a visual timeline of your day as events:
- WokeUp(7:00am)
- AteBreakfast(7:30am)
- StartedLearning(8:00am)
- HadInsight(8:15am)
Purpose: Experience thinking in events vs state!
Take 3 min to draw, 2 min to reflect on the difference between storing "CurrentState" vs "EventHistory"
π Connections to Previous Learning
From Month 1:
- Distributed Systems (M1W1): Events are naturally distributed and ordered
- Consensus (M1W2): Event ordering relates to Raft log replication
- Time (M1W2): Event timestamps and ordering challenges
- Complex Systems (M1W3): Events as state transitions in complex systems
Building Forward:
- Tomorrow (CQRS): Events separate writes from reads
- Day 3 (Sagas): Events coordinate distributed transactions
- Day 4 (Streams): Events as continuous data streams
β Daily Deliverables (Must Complete)
- [ ] Watch Greg Young's Event Sourcing video
- [ ] Read Martin Fowler's Event Sourcing article
- [ ] Implement basic event store with 3 event types
- [ ] Create account and perform 2 operations
- [ ] Demonstrate state reconstruction from events
- [ ] Draw event sourcing sequence diagram
- [ ] Write 3 key insights about event sourcing
β Bonus (If Extra Time)
- [ ] Add snapshot functionality to event store
- [ ] Implement event versioning
- [ ] Handle event ordering and concurrency
- [ ] Read about Event Store database
- [ ] Explore event sourcing in microservices
π― Success Criteria
By the end of today, you should be able to:
- β Explain what event sourcing is and why it's useful
- β Describe the difference between events and state
- β Implement a simple event store
- β Reconstruct state from event history
- β Identify when event sourcing is appropriate
- β Understand event sourcing trade-offs
β° Total Estimated Time (OPTIMIZED)
- π Core Learning: 35 min (video 15 + reading 15 + synthesis 5)
- π» Practical Activities: 25 min (implementation 15 + diagram 7 + reflection 3)
- π¨ Mental Reset: 5 min (event timeline drawing)
- Total: 60 min (1 hour) β
Note: Focus on understanding over perfection. A simple working event store that demonstrates the core concept is excellent for day 1!
π Today's Big Ideas
- Events Are Facts: They never change, only accumulate
- State Is Derived: Current state = replay all events
- Time Travel: You can reconstruct any past state
- Audit Trail: Perfect history of what happened when
- Flexibility: Multiple read models from same events
π Tomorrow's Preview
CQRS: Command Query Responsibility Segregation
You'll discover how separating writes (commands) from reads (queries) enables incredible scalability and flexibility. Event Sourcing + CQRS = π₯
"In event sourcing, the events are the source of truth, not the current state." - Greg Young
You're building production-grade patterns! πͺ