0
0
Microservicessystem_design~7 mins

Event sourcing pattern in Microservices - System Design Guide

Choose your learning style9 modes available
Problem Statement
When systems store only the current state, any data corruption or bugs can cause permanent loss of historical information. This makes debugging, auditing, and recovering past states difficult or impossible. Additionally, concurrent updates can lead to conflicts without a clear history of changes.
Solution
Event sourcing solves this by storing every change to the system as a sequence of events. Instead of saving just the latest state, the system records all state changes in order. The current state can be rebuilt anytime by replaying these events, providing a complete history and enabling easier debugging and recovery.
Architecture
Client/Service
Event Store
Event Replay

This diagram shows how client requests generate events stored in the event store. Events are processed and can be replayed to rebuild the current state or update read models.

Trade-offs
✓ Pros
Provides a complete audit trail of all changes for debugging and compliance.
Enables easy recovery of past states by replaying events.
Supports complex business logic with clear event history.
Facilitates integration with other systems via event streams.
✗ Cons
Increases storage needs since all events are kept indefinitely.
Rebuilding state by replaying events can be slow if event history is large.
Requires careful design to handle event versioning and schema evolution.
Use when auditability, traceability, or complex state transitions are critical, especially in systems with high write volumes or complex business rules.
Avoid when system state changes are simple and infrequent, or when storage and replay overhead outweigh benefits, such as small-scale CRUD apps.
Real World Examples
Amazon
Uses event sourcing in order management to track every change in order status, enabling full audit and recovery.
Uber
Applies event sourcing to track trip lifecycle events, allowing reconstruction of trip states and debugging of issues.
LinkedIn
Uses event sourcing for activity feeds to capture user actions as events, enabling flexible feed generation and replay.
Code Example
The before code updates the account balance directly, losing history. The after code records each change as an event in an event store and rebuilds the balance by replaying these events, preserving full history.
Microservices
### Before: naive state update without event sourcing
class Account:
    def __init__(self):
        self.balance = 0

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        self.balance -= amount


### After: event sourcing with event log
class EventStore:
    def __init__(self):
        self.events = []

    def append(self, event):
        self.events.append(event)

    def get_events(self):
        return self.events

class Account:
    def __init__(self, event_store):
        self.balance = 0
        self.event_store = event_store
        self.replay_events()

    def replay_events(self):
        for event in self.event_store.get_events():
            self.apply(event)

    def apply(self, event):
        if event['type'] == 'deposit':
            self.balance += event['amount']
        elif event['type'] == 'withdraw':
            self.balance -= event['amount']

    def deposit(self, amount):
        event = {'type': 'deposit', 'amount': amount}
        self.event_store.append(event)
        self.apply(event)

    def withdraw(self, amount):
        event = {'type': 'withdraw', 'amount': amount}
        self.event_store.append(event)
        self.apply(event)
OutputSuccess
Alternatives
CRUD-based state storage
Stores only the current state in a database without recording changes as events.
Use when: When system complexity is low and audit/history is not required.
Command Query Responsibility Segregation (CQRS)
Separates read and write models but does not necessarily store all changes as events.
Use when: When read and write workloads differ significantly but full event history is not needed.
Summary
Event sourcing stores all changes as a sequence of events instead of just current state.
This pattern enables full history tracking, easier debugging, and state recovery by replaying events.
It is best suited for systems requiring audit trails or complex state transitions but adds storage and complexity overhead.