The Logbook of Truth: Understanding Event Sourcing and CQRS
Fully AI-generated content. This article was generated using AI systems (e.g. Claude Code, Perplexity) and may contain errors or hallucinations.
Software Architecture · 2026-06-21 · approx. 30 minutes
The Hook: What a Bank Does Better Than Your Database
Imagine you ask your bank how much money is in your account. It names an amount — say, €4,231.57. Now imagine you ask the bank why it is exactly this amount. A reputable bank does not shrug. It hands you a statement: a complete, chronological list of every single transaction — salary deposit, direct debit, transfer, fee. The balance is not the actual truth. The truth is the sequence of transactions. The balance is merely a summary that can be recomputed from this sequence at any time.
And now the uncomfortable comparison: most software systems that you and I build do exactly the opposite. They store only the balance. In a typical database, a row holds balance = 4231.57. When a new transaction arrives, this value is overwritten with UPDATE — and the old value is gone forever. The system knows what currently holds, but no longer how it got there. It has no memory, only a state.
Event Sourcing inverts this logic. The idea, succinctly described by Martin Fowler in 2005, is: do not store the current state, but every individual state change as an immutable event in a chronological, append-only sequence. The current state is then no longer a stored fact but a computed result — the sum of all events, just as the balance is the sum of all transactions.
This initially sounds like unnecessary effort. Why keep the entire history if you only need the current value? The answer is surprisingly profound and ranges from complete auditability, through time travel in code, to one of the most elegant answers to the scaling problems of modern cloud systems. This article takes you the whole distance: from the core concept, through the closely related partner CQRS, several concrete real-world examples, an honest reckoning of the considerable downsides, to the question of when you should use these patterns — and, almost more important, when not.
Part 1: The Core Concept — State as a Computed Result
The Fundamental Difference from CRUD
The prevailing paradigm of data management is called CRUD: Create, Read, Update, Delete. An entity — a customer, an order, a document — lives as a record in a table. When something changes, the record is modified in place. This is simple, intuitive, and entirely sufficient for the overwhelming majority of all applications.
The price of this simplicity, however, is an information loss with every write. Every UPDATE and every DELETE destroys information. If a customer has changed their delivery address three times, a CRUD system knows only the last one. The intermediate steps, the timing, the reason — all irretrievably lost, unless you have laboriously logged them in additional audit tables.
Event Sourcing redefines the basic unit of truth. Martin Fowler formulates the core idea this way: every change to the state of the application is captured in an event object, and these event objects are stored in the order in which they were applied — and for the same lifetime as the application state itself. The event store thereby becomes the single source of truth. It is append-only: events are only added, never changed or deleted. An event once written is a historical fact, and one does not retroactively alter facts.
Events Are the Past, Commands Are Intent
A linguistic subtlety that sharpens understanding enormously: events are named in the past tense, because they describe something that has already happened and can no longer be rejected. OrderPlaced, ItemAddedToCart, DeliveryAddressChanged, PaymentReceived. An event no longer needs any validation — it is the record of a fact.
To be distinguished from this is the command: an intent to do something, formulated in the imperative — PlaceOrder, ChangeDeliveryAddress. A command can fail. The business logic checks it, and only if it is valid does it produce one or more events. This distinction — rejectable intent versus incontrovertible fact — is the conceptual backbone of the entire approach.
The Reconstruction: From Event Stream to State
If only events are stored, how do you arrive at the current state? Through replay: you take the initial state (typically "empty") and apply all events of the relevant entity in order. Each event is a pure function that transforms an old state into a new one. In functional notation, the current state is simply a fold (a fold or reduce) over the event stream:
currentState = events.reduce(apply, emptyState)
For a bank account: start at 0, apply Deposited(100) → 100, apply Withdrawn(30) → 70, apply Deposited(50) → 120. The balance of 120 was stored nowhere; it was computed. In C#, such an aggregate reconstruction might look like this:
public Account Reconstruct(IEnumerable<IEvent> events)
{
var account = new Account();
foreach (var e in events)
account.Apply(e); // mutates the state per event
return account;
}
Snapshots Against the Performance Problem
The attentive reader sees the problem immediately: an account with 50,000 transactions would have to run through 50,000 events on every read access. That does not scale. The established solution is called the snapshot: at regular intervals (say, every 100 or 500 events), the full computed state is stored as a momentary snapshot, tagged with the version number of the last included event. On reconstruction, you load the most recent snapshot and replay only the few events added since. The snapshot here is pure cache — it contains no new information and can be discarded and recomputed at any time. The truth remains the event stream.
Part 2: CQRS — the Natural Partner
Why Reading and Writing Need Different Models
CQRS stands for Command Query Responsibility Segregation. Martin Fowler summarizes the gist this way: you can use a different model to update information than the model you use to read information. In classical architectures you use a single data model for both — the same classes, the same tables, the same structure for writing and reading. CQRS deliberately breaks this symmetry and cleanly separates the command side (writing, state changes, validation of business rules) from the query side (reading, displaying, reporting).
The reason is that the requirements on the two sides often run diametrically apart. The write side must enforce business rules, preserve consistency, and handle conflicts — it is organized around correctness. The read side must be fast, denormalized, and tailored exactly to the needs of the particular view — it is organized around speed and convenience. A single model for both purposes is often a lazy compromise that fully satisfies neither side.
The Ideal Symbiosis with Event Sourcing
CQRS and Event Sourcing are independent patterns — you can use either without the other — but they complement each other strikingly well. Microsoft's Azure Architecture Center describes the usual combination this way: Event Sourcing is frequently combined with CQRS by performing the data-management tasks in response to the events and by materializing views (projections) from the stored events.
The mechanics behind it are elegant. The command side does nothing other than append events to the store — an extremely fast, low-conflict operation. In the background, projections listen to this event stream and build optimized read models from it: a relational table for search, a denormalized document for the detail view, an Elasticsearch index for full-text search, a precomputed metric for a dashboard. From one event stream, arbitrarily many read models, each shaped to the use case, can be derived — and when a new display need arises, you simply build a new projection and replay the entire history through it.
This separation also makes it possible to scale read and write load independently. In many systems, reads outnumber writes by orders of magnitude. With CQRS you can scale the query side horizontally across many replicas without touching the write side — a particularly valuable lever in the cloud.
The Price: Eventual Consistency
Here lies the central catch, and it is worth naming it with relentless honesty. Between the moment a command writes an event to the store and the moment all projections have processed this event and updated their read models, time passes. In this window, the read side shows a stale state. The system is not immediately, but only eventually consistent.
Microsoft's architecture guidance is unambiguous here: eventual consistency between the event store and the projections is inherent to Event Sourcing, because the system is consistent only once it has produced its materialized views by replaying the events. Concretely, this means: a user places an order, the event is persisted immediately — but the order overview they see next may not yet show the order, because the projection lags a few milliseconds behind (or, under load, longer). Anyone using Event Sourcing with CQRS must plan for this behavior in the UX design and in the business processes. It is not a weakness of the implementation but a deliberate architectural trade-off — a classic case of the CAP theorem, where one forgoes immediate consistency in favor of availability and partition tolerance.
Part 3: Concrete Examples from Practice
Example 1: The E-Commerce Shopping Cart
Consider an online shopping cart. In the CRUD model you store the current contents — three items, certain quantities. You know no more than that. In the Event Sourcing model you store the history:
ItemAdded(Book, 1)
ItemAdded(Pen, 5)
QuantityChanged(Pen, 3)
ItemRemoved(Book)
CouponRedeemed("SUMMER10")
The current cart (pens ×3, coupon active) results from the replay. But now comes the business value that CRUD could never deliver: marketing can analyze which items are particularly often removed again (a signal of purchase abandonment or price pain). It can analyze cart abandonments, because the entire path to abandonment is preserved. The data that a CRUD DELETE would simply have destroyed is here a valuable analytical treasure. This property — that information of business interest is preserved as a by-product of the architecture — is one of the most underappreciated advantages of the approach.
Example 2: Version Control as an Event Store You Use Daily
Perhaps the most compelling example you have already used today: Git. A Git repository does not store the current state of your files as the primary truth. It stores an append-only sequence of commits — each commit is essentially an event ("these changes were applied"). The current state of your working directory is the replay of all commits up to a certain point.
From this follows immediately why Git is so powerful: you can travel back to any historical state (git checkout), inspect the complete history (git log), trace who changed what, when, and why (git blame), and run alternative realities in parallel (branches). All of these are direct consequences of the Event Sourcing nature. If you understand Git, you already understand Event Sourcing intuitively — you just never called it that.
Example 3: LMAX — Event Sourcing for Extreme Performance
A common misconception is that Event Sourcing is slow. The counterexample is legendary: the LMAX architecture, also documented by Martin Fowler. LMAX is a trading platform for financial products, whose central "Business Logic Processor" handles around 6 million orders per second on a single thread — entirely in memory and based on Event Sourcing.
The trick: because the entire state is reconstructible from the event stream, the processing core need not consult any database during processing at all. It keeps everything in RAM and thereby gains enormous speed. If the system crashes, the state is restored by replaying the persisted events. Here Event Sourcing is the right choice not despite, but because of, the performance requirements. The pattern decouples the expensive persistence (sequential appending, very fast) from the business logic (in memory, without I/O wait times).
Example 4: Accounting, the Archetype
Double-entry bookkeeping was codified in the 15th century and is, at its core, Event Sourcing avant la lettre. A bookkeeper never erases a wrong entry. Instead, they post a correcting entry (reversal) — a new event that offsets the error. The history remains untouched and auditable. This centuries-old discipline is the reason Event Sourcing fits so naturally in financial, insurance, and compliance domains: there, the complete, immutable history is not an extra but a legal obligation.
Part 4: The Superpowers — What Only Event Sourcing Can Do
Beyond the individual examples, the structural advantages can be bundled into an overview.
| Capability | What it means | Why CRUD cannot do it |
|---|---|---|
| Complete audit log | Every change is permanently captured with timestamp, trigger, and context | CRUD overwrites; auditing requires separate, error-prone extra machinery |
| Time travel (temporal query) | The state at any past moment is reconstructible | CRUD knows only the now |
| Debugging by replay | A production bug can be reproduced by replaying the same events | CRUD has already forgotten the error-causing path |
| New projections retroactively | A new analysis is computed over the entire history, even over data that arose before its conception | CRUD can only collect from the moment someone thought of it |
| Retroactive correction | Faulty logic can be corrected and the history replayed with the corrected logic | CRUD has no source data for a recomputation |
The point of new projections retroactively in particular is a game changer in practice. In a CRUD system the bitter sentence holds: "Data we did not collect is lost forever." If management asks, a year after launch, for an analysis no one thought of at design time, a CRUD system can only collect data from today on. An Event Sourcing system builds the analysis over the full history — as if you had had it from the start. The past is not over; it lies in the event store, waiting for new questions.
Part 5: The Honest Reckoning — the Considerable Downsides
It would be disreputable to sell Event Sourcing as a cure-all. Martin Fowler himself expressly warns, regarding CQRS, that it adds risky complexity for most systems and should be used only when a clear benefit justifies the added cost. The same caution applies to Event Sourcing. An empirical study by Overeem and colleagues (2021, based on 19 production systems and the experience of 25 engineers) has precisely worked out the real pain points. I consider this scientifically grounded inventory more valuable than the mostly euphoric blog posts.
Schema Evolution: The Hardest Problem
Events are immutable facts and often lie in the store for years. But business requirements change, and with them the structure of the events. What do you do when an event written three years ago lacks a field that your current logic expects? You cannot simply change the old events — that would violate the basic principle. The aforementioned study identifies the evolution of the event system as one of the greatest challenges and names five established tactics: versioned events, weak schema (tolerant deserialization), upcasting (transforming old events into the new form on load), in-place transformation, and copy-and-transform. The researchers' recommendation: begin with versioned events and weak schema, later move to upcasting. But whichever tactic you choose — schema evolution remains a permanent, demanding maintenance effort that simply does not exist with CRUD.
Steep Learning Curve and Missing Tools
The same study names the steep learning curve and the lack of mature technologies as further core problems. Event Sourcing requires a fundamental rethink — developers who have thought in CRUD terms for years must internalize concepts like aggregates, projections, idempotency, and eventual consistency anew. Mistakes in this model are often subtle and expensive. On top of that: the tool ecosystem is markedly thinner and less standardized than for relational databases. There are specialized solutions (such as EventStoreDB, Marten for PostgreSQL in the .NET world, or Axon in the Java world), but nothing with the maturity, prevalence, and tooling density of an ordinary SQL database.
Eventual Consistency as a Permanent Burden
The consistency window described in Part 2 is not a one-time design problem but a constant burden on development and user experience. Every feature that wants to read immediately after a write ("read-your-own-writes") must be consciously handled — for example, through optimistic UI updates, by waiting for a particular projection version, or through targeted exceptions to the separation. This complicates nearly every use case.
Data Protection and the Right to Be Forgotten
A particularly thorny point in Europe, which the study also lists as a challenge of its own ("data privacy"): the GDPR grants a right to erasure. Event Sourcing, however, is based on an immutable, append-only log — deletion contradicts the basic principle. How do you delete personal data from a store whose very essence is immutability? The usual answer is crypto-shredding: you encrypt personal data in the events with a user-specific key and, when needed, delete only the key. The events remain physically intact but become undecryptable and thus effectively inaccessible. This is an elegant but non-trivial added complexity that must be planned in from the start — and whose legal soundness must be carefully examined case by case.
Part 6: The Decisive Question — When to Use It, When Not?
From weighing the superpowers against the burdens, a pragmatic decision rule emerges. It is more important than any technical detail question.
Event Sourcing pays off when:
The domain is event-based by nature and the history itself has business value — financial transactions, accounting, insurance claims, order processing, inventory movements, medical histories. When auditability is a hard regulatory requirement (banks, insurers, healthcare). When the ability to reconstruct past states or analyze behavior retroactively is a genuine business advantage. When extreme write performance or independent read scaling is required (as with LMAX).
Event Sourcing hurts when:
The domain is at its core simple CRUD — master-data maintenance, user profiles, configuration management, a content-management system. Here the history is usually irrelevant, and the added complexity is pure ballast without payoff. Microsoft's guidance puts it succinctly: Event Sourcing need not be an all-or-nothing decision for the whole system. Apply it selectively to the parts that benefit most — such as a payment ledger or an order pipeline — and use classical CRUD where the complexity is not justified, for instance in managing user profiles or application configuration.
It is precisely here that the maturity of an architect shows. The temptation to apply a fascinating pattern everywhere is great — and leads to "résumé-driven development," in which the architecture serves the developer's résumé and not the problem. I am of the view that the most valuable competence does not lie in being able to implement Event Sourcing, but in honestly judging whether a concrete subsystem needs it at all. In practice this almost always means: Event Sourcing only for the few, business-"hot" core domains, classical CRUD for the great rest. This hybrid strategy — a thought that fits well with the architectural trade-offs from Ist die Cloud valide — is by far the most common and healthiest form of use.
Part 7: The Connection to the Cloud and to Event-Driven Systems
Event Sourcing is not an isolated pattern but part of a larger movement toward event-driven architectures, which thrive especially well in the cloud era. The natural append-only structure fits superbly with modern streaming platforms like Apache Kafka, with cloud services like Azure Event Hubs or AWS Kinesis, and with serverless, reactive processing models.
The deeper reason: in distributed cloud systems, immediate, global consistency is physically expensive or impossible anyway. Eventual consistency there is not a special case but the norm. Event Sourcing makes this reality explicit and manageable, rather than hiding it behind a deceptive façade of apparent instant consistency. The events also become the natural integration mechanism between microservices: a service publishes its events, other services react to them and build their own views — a loose, robust coupling. The event store thereby becomes not only the memory of a single service, but the nervous system of an entire service landscape.
This connection of data-centric architecture and decoupled, reactive processing is also the point at which the bridge to modern AI and data pipelines can be built: a complete event stream is an ideal, gap-free training and analysis dataset — a thought that links the topic to the considerations from Der Wettlauf mit der (um die) KI.
The Central Takeaway
Event Sourcing is, at its core, a single, profound inversion: do not store the state, store the history — the state then follows by itself. This shift of the "source of truth" from the current value to the immutable sequence of events grants you complete auditability, time travel, retroactive analyses, and robust scaling — bought with considerable complexity in schema evolution, consistency, tooling, and data protection.
CQRS is the natural partner: the clean separation of write and read models, which makes it possible to materialize arbitrarily many optimized views from one event stream and to scale read and write load independently — at the price of eventual consistency.
The most important lesson, however, is an architectural stance: these patterns are sharp specialist tools, not a standard hammer. Their value arises only where the history itself matters in business terms. Everywhere else they are expensive ballast.
A concrete prompt to act on this week: Take a system you know well and ask a single question — "For which entity in this system would it bring us real business value to know not just the current state but the complete change history?" If you find a convincing answer (typically around money, contracts, inventory, or regulated processes), you have identified a real candidate for Event Sourcing. If you find none, you have just confirmed that CRUD is the right, honest choice — and that too is a valuable result.
A reflection question: Which valuable information do your current systems destroy with every UPDATE and DELETE, without anyone noticing — and which question might be put to you in two years that you cannot answer today only because you threw the past away?
Cross-References in the Vault
- Ist die Cloud valide – Architecture and trust questions in the cloud; the hybrid strategy (Event Sourcing only for core domains) is a direct application of the weighing of benefit and risk discussed there.
- Der Wettlauf mit der (um die) KI – A complete event stream is an ideal, gap-free dataset for analysis and AI training; data-centric architecture and AI interlock.
- Spooky Action at a Distance: Quantum Entanglement from Einstein to the Quantum Internet – There too, consistency across distance and the limits of instantaneous information play a central role; the CAP theorem is, in a sense, the "no-signaling theorem" of distributed systems.
Sources and Further Reading
- Martin Fowler – Event Sourcing (eaaDev, 2005): https://martinfowler.com/eaaDev/EventSourcing.html
- Martin Fowler – CQRS (bliki): https://martinfowler.com/bliki/CQRS.html
- Microsoft Learn – Event Sourcing Pattern (Azure Architecture Center): https://learn.microsoft.com/en-us/azure/architecture/patterns/event-sourcing
- Martin Fowler – The LMAX Architecture: https://martinfowler.com/articles/lmax.html
- Overeem, Spoor, Jansen, Brinkkemper – An Empirical Characterization of Event Sourced Systems and Their Schema Evolution — Lessons from Industry (Journal of Systems and Software, 2021): https://www.sciencedirect.com/science/article/pii/S0164121221000674 (Preprint: https://arxiv.org/abs/2104.01146)
- Microsoft Learn – Event-Driven Architecture Style (Azure Architecture Center): https://learn.microsoft.com/en-us/azure/architecture/guide/architecture-styles/event-driven
Created as part of the daily learning workflow. Field of interest: Software Architecture. Estimated reading time: ~30 minutes.