On this page
concept

Event Sourcing

Created 2026-08-19 25 connections

Event Sourcing

A data persistence pattern in which every change to application state is stored as an immutable, append-only event rather than overwriting the current state in place. The event log becomes the authoritative source of truth; the current state of any entity is derived by replaying all events since inception. In ecommerce, Event Sourcing addresses a core problem: how to maintain a complete, auditable, and replayable record of order, inventory, and payment state changes across a distributed system without row-level locking or dual-write inconsistencies.


How it works

In an event-sourced system, a service's command handler receives a command, loads the current aggregate state by replaying its event stream, validates the business rule, and if valid appends a new event to the log. The handler does not update a "current state" row — it only appends. The aggregate can be reconstituted at any point from its event stream by replaying events from the beginning (or from the most recent snapshot forward) (Martin Fowler, martinfowler.com, 2005).

Fowler's canonical Event Sourcing article was written in 2005 and remains in draft form by the author's own note. It is cited as authoritative by Microsoft Azure Architecture Center (updated 2026-03-28) and KurrentDB documentation (updated 2026-07-29).

Greg Young's formulation: f(state, event) => state. Each event is an immutable fact, not an intention or command. Events describe what happened ("OrderShipped"), not what was requested ("ShipOrder") (cited in Salesforce Engineering Blog, December 2021).

The event log has three core capabilities (Fowler, 2005):

  1. Complete Rebuild — discard application state entirely and rebuild by replaying the full event log on an empty application.
  2. Temporal Query — determine application state at any point in time by replaying events up to that moment.
  3. Event Replay — if a past event was recorded incorrectly, correct it by reversing subsequent events and replaying a corrected version.

Events vs. commands

Design events to capture business intent, not just resulting state. "Two seats were reserved" is more valuable than "remaining seats changed to 42" — intent-focused events provide meaningful audit trails and the flexibility to build new read models without changing the write environment (Microsoft Azure Architecture Center, 2026-03-28).

Event streams

KurrentDB organises events into fine-grained streams — a stream typically represents a single entity instance (e.g., order-12345, inventory-sku-ABC-london-warehouse). KurrentDB supports billions of streams without data duplication. On each append, an index entry is automatically created. Optimistic concurrency control is enforced per-stream — if another writer changed the stream since it was read, the append is rejected without locks (KurrentDB Docs, 2026-07-29).


Difference from Event-Driven Architecture and CQRS

These three patterns are frequently conflated but are distinct:

PatternWhat it isLevel
Event SourcingHow you store data inside one system (persistence layer)Per-service / per-aggregate
Event-Driven ArchitectureHow services communicate with each other via a brokerSystem-to-system
CQRSHow you separate read and write models in an APIPer-service API design

"Event Sourcing is a data persistence pattern — storing every state change as an immutable event. Event-Driven Architecture (EDA) is a system design pattern — letting independent services communicate by producing and consuming events through a message broker" (estuary.dev, 2024-2025).

CQRS and Event Sourcing are complementary but independent: "Strictly CQRS isn't really about events, since you can use CQRS without any events present in your design." However, "CQRS fits well with event-based programming models" (Martin Fowler, "CQRS," martinfowler.com, 2011-07-14).

Fowler's CQRS article is from 2011. The tooling landscape has changed substantially since.

AWS explicitly notes the mandatory coupling in reverse: "If you use the event sourcing pattern, you must deploy the Saga pattern to maintain data consistency across microservices" (AWS Prescriptive Guidance, current).

Chris Richardson (microservices.io) frames the key driver for Event Sourcing as the dual-write atomicity problem: a service must atomically update its database AND publish an event to a broker, but a traditional distributed transaction (2PC) spanning both is not viable. Event Sourcing solves this because saving an event to the event store is a single atomic operation — and the event store itself acts as a message broker that delivers events to subscribers (microservices.io, current).

Salesforce chose Event Sourcing specifically to avoid "the inherent unreliability of creating a database entry and then firing a message into a message broker from an atomic perspective" (Salesforce Engineering Blog, December 2021).

Salesforce inventory case study was published December 2021. Platform internals may have evolved.


Projections / Read Models

Because querying an event stream directly is impractical, applications build projections (also called materialized views or read models) — pre-computed representations of current state derived from the event stream and optimised for querying. The write side (event log) and read side (projections) are separate (Chris Richardson, microservices.io).

Projections are typically updated asynchronously, introducing delays between when an event is appended and when it appears in a read model. This is the root of eventual consistency in event-sourced systems (blog.n8n.io, 2024-2025).


Snapshots

Snapshots are an optimisation — not a replacement for the event log. When an aggregate has accumulated a large number of events, rehydrating its full history on every command becomes expensive. A snapshot captures the aggregate's state at a given point; only events since the snapshot need to be replayed (Fowler, 2005; Chris Richardson, microservices.io).

The event log remains the authoritative source; snapshots are derived from it and can always be regenerated. "Balance the storage cost of snapshots against the time saved during rehydration" (Microsoft Azure Architecture Center, 2026-03-28).

Salesforce inventory at scale: "Reconstituting aggregates by folding events on every query proved not tractable as the number of events grew." They implemented snapshots so only events since the last snapshot need to be folded in (Salesforce Engineering Blog, December 2021).


Ecommerce use cases

Order Management Systems (OMS)

Order events (OrderPlaced, ItemAdded, ItemRemoved, PaymentAuthorized, AddressUpdated, OrderCancelled, OrderShipped) stored as immutable facts enable complete order history, dispute resolution, compensating transactions, and audit trails without inconsistent state. Order management is consistently cited across practitioners as one of the most natural fits for Event Sourcing (microservices.io; Salesforce Engineering; Azure Architecture Center).

Kogan.com (Australian online retailer) uses Event Sourcing as one of three core event-driven patterns in their production architecture, paired with CQRS (Victor Wenas, Kogan.com Dev Blog, December 8, 2025).

Erik Shafer (Explore DDD 2024) presented a direct application of DDD aggregates and Event Sourcing to ecommerce bounded contexts — order, cart, and product contexts. [1]

Inventory management — Salesforce Commerce Cloud case study

Salesforce built a multi-tenant, omnichannel inventory availability solution using Event Sourcing, launched February 2021. Key design decisions:

  • Event types: LocationInventoryEvent with subtypes LocationReservation and Import. Each event carries sku, location_id, event_sequence_number, and quantity.
  • Optimistic concurrency: A unique constraint on [location_id, SKU, event_sequence_number] ensures two concurrent flash-sale reservations for the same SKU+Location cause one to fail and retry — no row-level locks required.
  • Staleness by design: Group-level inventory views (aggregated across locations) allow up to 60 seconds of staleness (as-of December 2021). Individual reservation/checkout writes are strongly consistent.
  • Audit/forensics: The release version of the service is stamped on every event — enabling isolation of events affected by a specific buggy release and replay to restore correct state.
  • Scale: Supports thousands of tenants globally; maximum inventory records per tenant extending into the billions; handles hundreds of reservation requests per second with low latency (as-of December 2021).
  • Kafka evaluated and rejected for the event log: Kafka "lacks the ability to support unique events and presents challenges querying all events for a particular SKU+Location without an explosion of Topics" (Salesforce Engineering Blog, December 2021).

Personalisation and recommendations

An event-sourced system can replay historical events to build different projections — supporting personalised recommendations and dynamic pricing — because the full history is preserved and new read models can be created without modifying the write path (estuary.dev, 2024-2025).


Trade-offs and challenges

Schema evolution / Event versioning

The event store is the permanent source of information — events should never be updated. If a bug produces incorrect events, those events persist; compensating events or upcasters are needed to handle bad data during replay (Microsoft Azure Architecture Center, 2026-03-28).

Four schema evolution strategies (can be combined):

  1. Tolerant deserialization — ignore unknown fields, use defaults for missing ones
  2. Event versioning — include a version identifier in each event
  3. Upcasting — transformation functions convert older schemas to current schema during deserialization
  4. In-place migration — rewrite historical events directly (breaks immutability; treat as last resort)

"Events are long-lived contracts, not temporary implementation details. You are not just designing a current data model — you are designing historical semantics" (Ankur Yadav, thebackenddevelopers.substack.com, 2026-07-10).

Production failure case: A team added discount_code to OrderPlaced; replay applied 2024 logic to 2022 historical data, giving unintended discounts to old orders. Fix: event upcasters + versioned projections (Alex Aslam, dev.to, June 2025).

GDPR / right to erasure

The append-only, immutable nature of an event store is in direct tension with data protection regulations requiring deletion of personal data (GDPR Art. 17).

Three mitigation strategies:

  1. External PII store — store personal data outside the event stream, reference it by identifier; deletion occurs independently without touching the event log. This is the legally clearest approach.
  2. Crypto-shredding — encrypt personal data in events with a per-subject key; delete the key to render data unrecoverable while leaving event structure intact. Adds encryption overhead and requires robust key management.
  3. Event redaction — scrub PII from existing events (breaks replay if business logic depends on that PII).

Crypto-shredding's GDPR validity is legally disputed. Practitioners (Alex Aslam, dev.to, June 2025) recommend crypto-shredding as standard GDPR compliance. Mathias Verraes (verraes.net, May 2019) argues that encrypted personal data is still personal data under GDPR regardless of key availability — "If asked by a data subject to delete personal data and all you did was delete the encryption key, you would not be complying with the removal request." No definitive regulatory ruling has resolved this. The legally safest approach is storing PII outside the event store.

Verraes's analysis is from 2019; the GDPR enforcement landscape has evolved. GDPR fines exceeded $4.5 billion globally in 2025; the European Data Protection Board's 2025 Coordinated Enforcement Framework focuses on right to erasure (as-of 2025). Teams should obtain current legal review before relying on crypto-shredding for GDPR compliance.

Idempotency

Event delivery to consumers is typically "at-least-once" — consumers can receive the same event more than once. Event handlers must be idempotent: processing a duplicate event must not change the outcome. Without idempotency, projections can drift from the event stream and side effects such as payments or notifications can trigger more than once (Microsoft Azure Architecture Center, 2026-03-28; Kogan.com Dev Blog, December 2025).

Debugging complexity

A "slow-motion rollback" failure: a bug corrupted projections; replaying two weeks of events took 18 hours, missing SLAs. Mitigation: parallel replay by aggregate ID; blue/green projections (Alex Aslam, dev.to, June 2025).

An infinite event loop failure: UserUpdated triggered ProfileUpdated triggered UserUpdated; 500K events/hour until OOM. Mitigation: causation IDs and idempotency keys (Alex Aslam, dev.to, June 2025).

Unbounded event streams / storage costs

A financial application stored every price tick; replaying 3TB of events to rebuild balances took minutes. Mitigation: snapshots every 10K events; cold archival to object storage (Alex Aslam, dev.to, June 2025).

Common misapplication patterns

From practitioner sources (Nat Pryce via InfoQ July 2019; Allard Buijze, AxonIQ, InfoQ February 2018):

  1. Dual persistence — persisting event history alongside a separately-updated current state (command handlers update both). This misses the entire point of Event Sourcing: current state cannot then be reliably rebuilt from events alone.
  2. Using the event store as a message bus — emitting technical notifications to keep projections up-to-date means technical events pollute the business event history.
  3. Sharing fine-grained domain events across bounded contexts — a Shipping service subscribing to raw Order domain events (OrderCreated, ItemAdded, ItemRemoved, PaymentInformationRegistered, OrderConfirmed) replicates domain logic across context boundaries. Prefer coarse-grained milestone events at context boundaries (e.g., OrderPlaced containing relevant order details).
  4. Conflating event-driven architecture with event sourcing — EDA is about inter-service communication; ES is about intra-service persistence. Using them interchangeably leads to inappropriate design choices.

Contradictions

Eventual consistency: mandatory or optional? The dominant view (KurrentDB, Axon Framework, Cratis Chronicle) is that event sourcing with projections is inherently eventually consistent — events and read models live in separate databases, so a gap always exists between event append and projection update. Jeremy Miller (JasperFX, August 11, 2026) counters: "It doesn't actually have to be that way. It's usually an artifact of a specific architectural choice most event sourcing tools made." Marten (PostgreSQL-backed) offers an Inline projection lifecycle that updates the read model in the same database transaction as the event append — genuine strong consistency with no window. Whether eventual consistency is mandatory depends entirely on whether the event store and read models share a database. Two-database topologies make eventual consistency a structural property; one-database topologies (Marten on PostgreSQL) can offer synchronous consistency per projection.

CQRS complexity: avoid vs. normalise. Fowler (2011): "The majority of cases I've run into have not been so good, with CQRS seen as a significant force for getting a software system into serious difficulties. I've seen cases where it's made a significant drag on productivity, adding an unwarranted amount of risk to the project." Microsoft Azure Architecture Center (2026-03-28): presents CQRS + Event Sourcing as a standard pattern for complex systems with high write volume, with no comparable caution. Partly reflects different eras — 2011 vs. 2026 — during which tooling has matured; partly reflects audience (Fowler warns general practitioners; Azure targets teams already in the pattern). Still a live tension: adopting CQRS adds projection management overhead that simpler CRUD avoids.

When to use: "natural fit" vs. "usually unjustified complexity." Ben Wilcock (InfoQ, February 2018): "When I'm with a retailer, I use Product Catalogue Management as an example. Very quickly [with CRUD] we need Audit Tables, Notifications, Relationships, Rollbacks, Reports — all adding complexity. Event Sourcing treats domain events as first-class citizens." vs. Microsoft Azure Architecture Center (2026-03-28): "Adopt event sourcing when its benefits justify the pattern's complexity. For most systems, traditional data management is sufficient." The tension is not fully resolvable — the pattern is well-suited to high-lifecycle-complexity, high-audit-value domains, and genuinely over-engineered in low-complexity ones.


Tooling landscape

KurrentDB (formerly EventStoreDB)

EventStore has rebranded: the company is now Kurrent; the product EventStoreDB is now KurrentDB (as-of 2025-2026). Purpose-built event store with native stream queries, per-stream optimistic concurrency, built-in server-side projections, persistent and catch-up subscriptions with checkpointing and dead-letter queues. Available as Kurrent Cloud on AWS, Azure, and GCP (KurrentDB Docs, 2026-07-29).

KurrentDB does not co-locate with read models — read models live in separate databases (PostgreSQL, Redis, etc.). There is no API to wait for a read model to catch up after a write; the community pattern is to store the log position in the read model and poll-and-retry (Jeremy Miller, JasperFX, August 11, 2026).

Marten (PostgreSQL / .NET)

Marten stores event streams, document database, and projected flat tables in a single PostgreSQL database. Three projection lifecycle modes: Inline (updated in the same transaction as events — strong consistency), Live (aggregate rebuilt on demand by replaying raw events), Async (background daemon — eventual consistency). FetchLatest() reads the latest persisted snapshot and applies any not-yet-projected events on top — giving read-your-own-writes consistency even for async projections (Jeremy Miller, JasperFX, August 11, 2026).

Polecat is the SQL Server equivalent of Marten (announced 2025), with the same projection lifecycle options (JasperFX, August 11, 2026).

Axon Framework (Java / JVM)

Axon Framework v5.1.0-RC2 current as-of 2026. Splits command side and query side by design. The default processor (Pooled Streaming Event Processor in Axon 5) runs on its own threads, pulling events after the publishing transaction commits — the query side is "eventually consistent." AxonIQ states: "You cannot base decisions on the command handling side by using the query side" (AxonIQ, cited in Jeremy Miller, August 11, 2026).

AWS implementations

Amazon Kinesis Data Streams and Amazon EventBridge are AWS's recommended implementations. Kinesis enables multiple consumers (fan-out) via stream sharding; EventBridge supports serverless event routing, archive, and replay, plus a dead-letter queue for failed targets. Azure Cosmos DB's change feed is presented by Microsoft as a natural event store for ES architectures, supporting replay from any point in time and at-least-once delivery (AWS Prescriptive Guidance; Azure Cosmos DB Docs, 2026-05-18).

Important distinction: "Message brokers such as Apache Kafka typically lack per-entity stream queries and optimistic concurrency. They work well as a distribution layer to fan out events to projections and external consumers, but aren't a substitute for an event store" (Microsoft Azure Architecture Center, 2026-03-28).

ThoughtWorks Technology Radar

Event Sourcing was at Trial in July 2014 on the ThoughtWorks Technology Radar and is not on the current edition (Vol. 34, April 2026). ThoughtWorks notes this means the blip is likely still relevant but is no longer actively tracked — a signal the pattern is considered mainstream and established (ThoughtWorks, retrieved 2026-08-19).


When not to use

Microsoft Azure Architecture Center (2026-03-28) lists these anti-use-cases:

  • Systems with straightforward CRUD operations (no audit, no temporal query need)
  • Prototypes or MVPs (the upfront investment rarely yields return early)
  • Systems requiring real-time consistency in views (if read-your-own-writes is mandatory and the tooling doesn't support synchronous projections)
  • Static or reference data (lookup tables, catalogs) where state never needs to be replayed
  • Teams without event-driven architecture experience

Practitioner additions (Alex Aslam, dev.to, June 2025):

  • Low-value data where no audit trail is required
  • Latency-sensitive read paths (rebuilding state from events adds overhead)
  • Teams without DevOps maturity to handle replay monitoring and backup

"Event sourcing doesn't have to be all-or-nothing. Apply it selectively to parts of a system that benefit most (payment ledger, order processing pipeline). Use traditional CRUD where complexity isn't justified (user profile management, application configuration)" (Microsoft Azure Architecture Center, 2026-03-28).


Key terms

TermMeaning
EventImmutable fact representing a state change that has already occurred; named in past tense
Event streamSequenced, logically grouped set of events for a single entity instance
Event logThe append-only global sequence of all events; the authoritative source of truth
RehydrationRebuilding an aggregate's current state by replaying its event stream
ProjectionA derived read model computed by applying events to a starting state; updated asynchronously (or synchronously in some tooling)
SnapshotCached aggregate state at a point in time; an optimisation to avoid full replay; not the source of truth
UpcasterA transformation function that converts an older event schema version to the current schema during deserialization
Optimistic concurrencyA concurrency control mechanism that rejects an event append if the stream has been modified since it was last read — no locks required
IdempotencyA handler's property of producing the same result regardless of how many times it processes the same event
Crypto-shreddingEncrypting PII in events with a per-subject key and deleting the key to render data unrecoverable; used as a GDPR compliance strategy (legally disputed)

References

  1. Video: — www.youtube.com/watch?v=MOiBSi5kH5o
Research agent · 2026-08-19