patternpythonModeratepending
Event Sourcing Pattern - When and How to Use It
Viewed 0 times
event sourcingCQRSaggregateevent storeaudit trailtemporal queries
Problem
Traditional CRUD overwrites data, losing the history of changes. Need full audit trail, temporal queries, or the ability to rebuild state from events.
Solution
Event sourcing stores state as a sequence of events:
When to use event sourcing:
When NOT to use:
# Events are immutable facts
class Event:
def __init__(self, event_type, data, timestamp=None):
self.event_type = event_type
self.data = data
self.timestamp = timestamp or time.time()
# Event store
class EventStore:
def __init__(self):
self.events = [] # In production: append-only DB table
def append(self, aggregate_id, event):
self.events.append((aggregate_id, event))
def get_events(self, aggregate_id):
return [e for aid, e in self.events if aid == aggregate_id]
# Aggregate rebuilds state from events
class BankAccount:
def __init__(self, account_id, event_store):
self.id = account_id
self.store = event_store
self.balance = 0
# Replay all events
for event in event_store.get_events(account_id):
self._apply(event)
def _apply(self, event):
if event.event_type == 'deposited':
self.balance += event.data['amount']
elif event.event_type == 'withdrawn':
self.balance -= event.data['amount']
def deposit(self, amount):
event = Event('deposited', {'amount': amount})
self.store.append(self.id, event)
self._apply(event)
def withdraw(self, amount):
if amount > self.balance:
raise ValueError('Insufficient funds')
event = Event('withdrawn', {'amount': amount})
self.store.append(self.id, event)
self._apply(event)When to use event sourcing:
- Financial systems (audit trail required)
- Collaborative editing (conflict resolution)
- Systems needing temporal queries ("what was the state on Jan 1?")
- Complex domain logic with many state transitions
When NOT to use:
- Simple CRUD apps
- When you don't need history
- When eventual consistency is unacceptable
Why
Events are append-only and immutable, providing a complete audit trail. You can rebuild the current state, project into different read models, and even fix bugs by replaying events.
Gotchas
- Event schema evolution is hard - use versioned events and upcasters
- Replaying millions of events is slow - use snapshots to checkpoint aggregate state
Context
Architectural decision for state management
Revisions (0)
No revisions yet.