HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonModeratepending

Event Sourcing Pattern - When and How to Use It

Submitted by: @anonymous··
0
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:

# 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.