| Scale | Users | Events per Second | Storage Growth | System Changes |
|---|---|---|---|---|
| Small | 100 users | ~10-100 EPS | Few MBs per day | Single event store instance, simple replay |
| Medium | 10,000 users | ~1,000-5,000 EPS | GBs per day | Event store clustering, read model caching, snapshotting |
| Large | 1,000,000 users | ~50,000-100,000 EPS | TBs per month | Event store sharding, asynchronous projections, CQRS separation |
| Very Large | 100,000,000 users | Millions EPS | Petabytes per year | Multi-region event stores, advanced partitioning, archival, strong consistency trade-offs |
Event sourcing pattern in Microservices - Scalability & System Analysis
Start learning this pattern below
Jump into concepts and practice - no test required
The event store database is the first bottleneck. It must handle high write throughput and fast reads for event replay and projections. As event volume grows, storage I/O and query latency increase, slowing down the system.
- Horizontal scaling: Add more event store nodes with clustering and partitioning (sharding) by aggregate or event type.
- Snapshotting: Periodically save aggregate state snapshots to reduce replay time.
- Read model caching: Use CQRS to separate read models and cache them for fast queries.
- Asynchronous projections: Build read models asynchronously to reduce write path latency.
- Archival: Move old events to cheaper storage to keep active event store performant.
- Multi-region deployment: Distribute event stores geographically to reduce latency and increase availability.
At 10,000 EPS, event store needs to handle ~10K writes/sec. A single node can handle ~5K QPS, so at least 3 nodes are needed for redundancy and load.
Storage: Assuming 1 KB per event, 10K EPS means ~864 MB/day. Requires scalable storage solutions.
Bandwidth: 10K EPS * 1 KB = ~10 MB/s write bandwidth, plus read traffic for projections.
Start by explaining event sourcing basics. Then discuss how event volume grows with users. Identify the event store as the bottleneck. Propose scaling with sharding, snapshotting, and CQRS. Mention trade-offs like eventual consistency and complexity.
Your event store database handles 1000 QPS. Traffic grows 10x to 10,000 QPS. What do you do first?
Answer: Add event store nodes and shard events by aggregate or event type to distribute load. Also implement snapshotting to reduce replay overhead.
Practice
Event sourcing pattern in microservices?Solution
Step 1: Understand event sourcing concept
Event sourcing means saving every change as an event, not just the final state.Step 2: Compare options with definition
Only Store all changes as a sequence of events instead of only the current state correctly describes storing all changes as events, others focus on snapshots or partial use.Final Answer:
Store all changes as a sequence of events instead of only the current state -> Option AQuick Check:
Event sourcing = storing all changes as events [OK]
- Confusing event sourcing with snapshot storage
- Thinking events are only for communication
- Believing events are stored only on errors
Solution
Step 1: Recall event sourcing flow
In event sourcing, changes are first recorded as events, then state is updated from those events.Step 2: Match options to flow
Create an event representing the change, then update the state from the event correctly shows event creation before state update; others do not follow this order.Final Answer:
Create an event representing the change, then update the state from the event -> Option CQuick Check:
Event first, then state update = Create an event representing the change, then update the state from the event [OK]
- Updating state before creating events
- Skipping event creation
- Sending events before state is updated
events = [
{"type": "Deposit", "amount": 100},
{"type": "Withdraw", "amount": 30},
{"type": "Deposit", "amount": 50}
]
balance = 0
for event in events:
if event["type"] == "Deposit":
balance += event["amount"]
elif event["type"] == "Withdraw":
balance -= event["amount"]
print(balance)Solution
Step 1: Calculate deposits and withdrawals
Deposits: 100 + 50 = 150; Withdrawals: 30Step 2: Compute final balance
Balance = 0 + 150 - 30 = 120Final Answer:
120 -> Option DQuick Check:
Deposits minus withdrawals = 120 [OK]
- Adding withdrawals instead of subtracting
- Ignoring last deposit event
- Starting balance not zero
Solution
Step 1: Understand event replay in event sourcing
State is rebuilt by replaying all events in order.Step 2: Effect of missing an event
If an event is missing, the rebuilt state will not reflect all changes, causing inconsistency.Final Answer:
State becomes inconsistent or incorrect -> Option BQuick Check:
Missing event = incorrect state [OK]
- Assuming system crashes on missing event
- Confusing missing event with duplicate events
- Thinking commands stop working due to missing event
Solution
Step 1: Identify performance issue in event sourcing
Replaying all events from the start can be slow as event count grows.Step 2: Choose solution to reduce replay time
Snapshots save the current state at intervals, so only recent events need replaying.Final Answer:
Use snapshots to save periodic state and replay only recent events -> Option AQuick Check:
Snapshots improve replay speed [OK]
- Discarding old events breaks event sourcing
- Sending all events elsewhere doesn't reduce replay
- Ignoring events after initial load loses audit trail
