Event Sourcing is an architectural pattern where application state is derived by storing and replaying a sequence of immutable events rather than persisting only the current state. It provides a full audit trail, temporal querying, and powerful debugging capabilities for complex systems.
Event Sourcing stores every change to application state as an immutable, time-stamped event in an append-only log. Instead of updating a single row in a database (e.g., 'balance = 500'), you record what happened (e.g., 'MoneyDeposited: $200'). The current state is always reconstructed by replaying events from the beginning or from a known snapshot. This log of events becomes the single source of truth for the entire system.
Event Sourcing gives you a built-in, complete audit trail with zero extra effort — every state transition is preserved forever. It enables powerful capabilities like time-travel debugging (replay events up to any point in time) and event-driven integration (other services subscribe to the event stream). Teams working in domains like finance, healthcare, or e-commerce — where every change must be traceable — find it especially valuable.
An aggregate (e.g., a BankAccount domain object) handles commands by validating business rules and emitting one or more events. Those events are persisted to an Event Store (such as EventStoreDB or a Kafka topic) and then applied to the in-memory state of the aggregate. To reload an aggregate, you fetch its event history and replay each event in order, rebuilding the current state from scratch. Snapshots can be introduced to avoid replaying thousands of events every time, caching state at a specific sequence number.
Traditional CRUD systems overwrite state, meaning history is permanently lost unless you explicitly build an audit log. Event Sourcing inverts this: history is the primary record, and current state is a derived projection. CRUD is simpler to start with, but Event Sourcing shines when auditability, retroactive bug fixes, or complex business logic around state transitions are required.
Because replaying events to answer every query would be slow, Event Sourcing is commonly paired with CQRS (Command Query Responsibility Segregation). Read models, called projections, listen to the event stream and maintain pre-computed, query-optimized views in a separate store (e.g., a SQL table or Elasticsearch index). Projections can be rebuilt at any time by simply replaying all events, which makes evolving your read model schema straightforward.
Events must be treated as permanent contracts — once published, you should never change or delete an event's schema without a versioning strategy, as doing so breaks replay. Use upcasting or versioned event types to handle schema evolution gracefully. Be careful with side effects in event handlers (e.g., sending emails); apply them only once on first processing, not on replay. Keep events small, intention-revealing, and focused on what happened in the domain rather than technical implementation details.
© RM Full Stack & AI Engineer · All guides · Roadmaps · Open the app