Create your own
Lesson illustration

Deriving Current State from Domain Events and Projections

Welcome. This first module establishes the central idea behind Event Sourcing: a system can preserve what happened as an ordered history of facts, then calculate the state it needs from that history.

For your client-information workflow, this matters because an AI-generated update, a gate’s decision, and a resulting canonical-data change are not the same fact. Event Sourcing gives us a way to retain each fact without letting an unapproved proposal silently become canonical data. In this lesson, you will learn the basic mechanism: append events, then use a projector to derive state.


From a scoreboard to a history

A conventional database often feels like a scoreboard: it tells you the current score, but not how the game unfolded. If a client record now says its legal name is “Northwind Health Ltd.,” the record alone may not tell you:

  • what the previous value was,
  • who or what proposed the change,
  • whether an automated gate approved it,
  • when it became authoritative.

Event Sourcing begins from the opposite direction. Rather than treating today’s record as the fundamental truth, it treats the sequence of meaningful facts that produced it as the truth.

Event Sourcing Explained Using Football

Watch “Event Sourcing Explained Using Football” from Metaphorically Speaking. The scoreboard-and-logbook analogy provides a compact mental model for the difference between stored current state and an event history from which state can be calculated.

Watch the scoreboard analogy. Focus on why a final score cannot reveal the sequence of goals, while a logbook can derive the score at any moment. Then watch projections and rebuilding. Notice that the scoreboard is useful and fast, but it is not the authority: it can be rebuilt from the persisted history.

The analogy has three direct counterparts in a software system:

Football exampleEvent-sourced system
Logbook of goals, cards, and substitutionsEvent store containing persisted domain events
One game’s timelineEvent stream for one business entity or boundary
ScoreboardProjection or read model derived from events

An event is a statement that a meaningful thing already happened. It is normally named in the past tense:

  • ClientRegistered
  • ClientInformationProposed
  • ProposalAccepted
  • ClientDataChangeApproved

These are facts, not requests. “Change the client’s name” is a request; “Client name changed” asserts that a change has occurred. We will distinguish requests, proposals, decisions, and events carefully in the next module. For now, hold onto the basic rule:

An event describes a completed domain fact, with enough context to understand and apply that fact later.

For example, a simplified approved change event might record the client, the approved field value, the decision that authorized it, and when it occurred. It should not merely say “the client is now updated,” because that loses the meaningful business story.


Append-only event streams

In Event Sourcing, events are placed into an append-only store. “Append-only” means that new facts are added to the end of the history; prior facts are not edited in place to make the history look different.

Event Sourcing pattern - Azure Architecture Center

Read Microsoft Azure Architecture Center’s “Event Sourcing pattern.” It establishes the core distinction between recording logical changes as events and reconstructing an entity’s state by replaying its ordered event history.

In the “Solution” section, read the core definition. Focus on the idea that each stored event represents one logical change, rather than a replacement of an entire record. In the following explanation of event streams, read the rehydration explanation. Then continue from “Materialized views are read-only projections of the event store” through the customer-order example: the read model passage. Distinguish on-demand replay for reconstructing an entity from a persisted view optimized for many queries.

An event stream is an ordered sequence of related events. A stream might represent the history of one client, one proposal, or another carefully chosen business boundary. We will decide those boundaries later; the key point today is that order is essential.

Consider a simplified stream about a client’s canonical contact information:

PositionEventRelevant fact
1ClientRegisteredClient C-204 was created with email contact@northwind.example
2ClientEmailChangeApprovedThe approved email became data@northwind.example
3ClientPhoneChangeApprovedThe approved phone became +1 555 0100

The current canonical contact state is not stored inside the third event. It is calculated by starting from an initial state and applying the events in recorded order.

Formally, if is the initial state and is the event at position , then:

For the example:

  1. Begin with no client contact data.
  2. Apply ClientRegistered; the email becomes contact@northwind.example.
  3. Apply ClientEmailChangeApproved; replace the email with data@northwind.example.
  4. Apply ClientPhoneChangeApproved; add the approved phone number.

The result is the current contact record. This act of reading events from the beginning and applying them in order is often called replay or rehydration.

Append-only does not mean “nothing can ever change”

Real information changes, and systems make mistakes. Append-only means that the history itself is preserved. If an approved phone number later proves wrong, the system records a new fact that corrects it. It does not rewrite the old event as though it never happened.

That distinction is important for your use case. A history may truthfully show that:

  1. an agent proposed a value,
  2. the value passed a gate,
  3. it was promoted,
  4. a later review found it incorrect,
  5. a corrected value was approved.

The current canonical value may be only the fifth event’s result, but the prior decisions remain explainable.


What a projector does

A projector is a component that consumes events and builds a useful representation of state. Its job is not to invent business history. Its job is to interpret already-stored history into a shape that a particular consumer needs.

A projector follows a simple conceptual routine:

  1. Start from an empty initial state, or from a previously stored projection state.
  2. Read events in their recorded order.
  3. Ignore events irrelevant to its purpose.
  4. Apply a transformation for each relevant event.
  5. Store the resulting state in a read model, dashboard, search index, or another query-oriented store.

For the canonical contact view above, a projector might have rules like:

Event typeProjection action
ClientRegisteredCreate the client’s initial display record
ClientEmailChangeApprovedSet the displayed canonical email
ClientPhoneChangeApprovedSet the displayed canonical phone
ClientInformationProposedIgnore it for the canonical-contact view

That final row is crucial. A proposal is evidence that someone or something suggested a change. It is not, by itself, evidence that the canonical client record should change.

The same underlying events can produce several projections. For example:

ProjectionPurposeEvents it cares about
Canonical client profileShow approved client informationRegistration and approved data-change events
Proposal review queueShow work awaiting acceptanceProposal and review-decision events
Governance timelineExplain what happened and whyMost events, including provenance and decisions

These views may contain different fields, use different storage technologies, and answer different questions. What binds them together is that they are all derived from the same durable facts.

A high-level CQRS and Event Sourcing architecture: the client submits commands that lead to stored events, a projection reads those events to maintain a query-oriented read model, and queries retrieve data from that read model.

The diagram includes Command Query Responsibility Segregation, often abbreviated CQRS. You do not need to master CQRS yet. For this lesson, read it simply as a separation between:

  • the part of a system that evaluates a requested change and records facts, and
  • the part that serves data efficiently from projections.

The important relationship is that the event store supplies the projector, and the projector supplies the read model. The read model is valuable because it avoids replaying a lengthy event history every time an application needs to display one client record or a list of pending proposals.


Two forms of deriving state

“Derive state from events” can mean two closely related activities. They use the same underlying logic but serve different purposes.

ActivityWhat happensTypical purpose
RehydrationLoad one entity’s stream and replay it into memoryUnderstand current state before evaluating a new requested action
ProjectionContinuously or periodically process events into stored viewsServe fast queries, reports, dashboards, and downstream consumers

Suppose a system receives a request to change a client’s canonical email. Before accepting that request, it may need to know the client’s present canonical status and current email. It can rehydrate that state from the client’s event history.

Separately, a web interface may need to show thousands of clients quickly. Replaying every client’s full history for every page load would be wasteful. A projector maintains a query-friendly client-profile view, so the interface can retrieve the already-derived result.

Both should agree because both are based on the same ordered history and the same interpretation rules. If a projection is deleted, corrupted, or replaced with a better design, it can be rebuilt by replaying the event store. That is why a projection is a derived artifact, not the source of truth.

A good projector is therefore as deterministic as practical: given the same events in the same order, it should compute the same result. It should rely on the recorded event data, rather than quietly consulting changing external information such as “today’s current rules” or a live third-party profile.


Applying the idea to proposed client-data updates

Now connect the foundation to your target architecture: AI agents propose changes to client information, but acceptance gates control whether those changes become canonical.

Imagine this high-level history:

PositionEventEffect on proposal viewEffect on canonical client view
1ClientRegisteredNo proposal yetCreates the client
2ClientInformationProposedShows a proposed address changeNo canonical change
3ProposalValidationCompletedShows validation outcomeNo canonical change
4ClientAddressChangeApprovedShows approved proposalUpdates canonical address

A proposal projector can interpret positions 2 and 3 to show reviewers what was suggested, by which agent, with what supporting evidence, and what the gates found.

A canonical-client projector has a narrower authority rule: it updates the canonical address only when it receives the accepted change event at position 4. It does not treat “a proposal exists” as “the canonical address changed.”

This is the architectural principle to retain:

Facts about proposed changes and facts about canonical changes may share a history, but a canonical-state projection must apply only the event types that carry the required authority.

The exact event names, identifiers, stream boundaries, and gate events will be designed in the next modules. At this stage, the central insight is simply that a projector makes authority visible in its transformation rules. It is not enough to store events; you must decide which events are allowed to affect which derived states.


A few boundaries to keep clear

Several ideas are easy to blur together at first.

The event store is not merely a transient notification channel. A message can be delivered and forgotten. An event store must durably preserve the ordered history needed to reconstruct state later.

A projection is not an independent source of truth. It can be optimized, indexed, reformatted, deleted, and rebuilt. If the projection disagrees with the event history, the event history is authoritative in a true event-sourced design.

An event is not a command. A command asks for an action; an event records the fact that resulted after the action was evaluated. This distinction becomes particularly important when an AI agent proposes an update that might be rejected.

Appending is not overwriting. New facts modify the calculated current state without erasing earlier facts. Correction normally means recording a later correction, not mutating old history.

For large histories, systems may use a snapshot: a stored state at a known event position. Rebuilding can then start from that snapshot and apply only later events. This is a performance optimization; the event stream remains the fundamental record.


Key takeaways

Event Sourcing stores an ordered, append-only history of domain facts. A current state is then calculated by replaying those facts from an initial state.

A projector is the component that performs this calculation for a specific purpose and often saves the result as a query-friendly read model. Different projectors can derive different useful views from the same event history.

For the AI-proposal workflow, the central design constraint is that a proposal event must not alter canonical client state merely because it exists. The canonical projection should react only to events that represent properly authorized, approved changes.

Next, you will compare Event Sourcing with CRUD persistence, audit logs, and record versioning. That comparison will make the meaning of “source of truth” and the update semantics of each approach much sharper.

Can't find a good explanation? Sign up and we'll make it for you

Sign up