Create your own
Lesson illustration

Event Sourcing vs. CRUD, Audit Logs, and Versioning

Good to see you again. In the previous lesson, you established the core Event Sourcing mechanism: retain an ordered, append-only stream of facts, then derive useful current-state views with projectors. Most importantly for the client-data workflow, a proposal does not change canonical client data simply because it was recorded; only an appropriately authorized event should affect the canonical projection.

This lesson sharpens that idea by comparing four approaches that can all appear to “keep history”: CRUD persistence, audit logging, record versioning, and Event Sourcing. The key distinction is not whether a system stores old information. It is which record is authoritative and what an update means operationally.


Two questions that separate the patterns

When comparing data architectures, begin with two questions.

1. What is the source of truth?

The source of truth is the record that resolves disagreements and from which the system is expected to recover its authoritative understanding.

For example, suppose a client-profile table says an email is legal@northwind.example, but another log says it changed twice since that value. Which one determines what the system currently believes? Which one would you use to rebuild the system after a derived view was lost?

Those questions reveal the authoritative record.

2. How does a change occur?

Update semantics describe what the system does when information changes:

  • Does it overwrite a field in the current record?
  • Does it add a separate audit entry after the change?
  • Does it preserve a prior row version and insert a newer version?
  • Does it append a domain fact and calculate the resulting state?

These choices determine more than storage structure. They determine how easily you can explain the past, correct mistakes, recover projections, and enforce your acceptance boundary.

Martin Fowler’s Event Sourcing is useful here because it explicitly distinguishes keeping an event record from merely keeping a history alongside current application state.

Event Sourcing

Read Martin Fowler’s explanation of how Event Sourcing differs from a basic service that persists only final state. Focus on his central test: can application state be discarded and reconstructed from the event history?

In “How it Works,” read from the core definition and comparison. Notice the point that a history or log file alone is not sufficient. Then, in “Application State Storage,” read the system of record distinction. Relate “application state” to the canonical client database in your intended architecture.


CRUD: current state is authoritative

CRUD stands for create, read, update, and delete. In a conventional CRUD system, a database table typically holds the latest known state of a business record.

A simplified canonical client table might look like this:

Client IDLegal nameCanonical emailStatus
C-204Northwind Health Ltd.contact@northwind.exampleActive

If an accepted request changes the email, the application updates the existing row. Afterward, the table might show:

Client IDLegal nameCanonical emailStatus
C-204Northwind Health Ltd.data@northwind.exampleActive

The older email is no longer in the authoritative row.

CRUD’s source of truth

The current record is authoritative. If a cache, report, or search index disagrees with the client table, the client table wins.

That is often exactly the right design. CRUD is direct, familiar, efficient for ordinary queries, and sufficient when the business mainly needs the current answer: What is this client’s approved address now?

CRUD’s update semantics

A change usually means:

  1. Load the current row.
  2. Validate the requested change.
  3. Overwrite one or more fields in that row.
  4. Commit the transaction.

The database preserves the final state, not necessarily the chain of facts that produced it.

A CRUD update can be fully governed. You can require that a gate approves changes before the application writes the canonical row. But unless you add another mechanism, the old value and the reason for the transition disappear from the primary record.

Important distinction: CRUD is not inherently careless or unauditable. It simply does not make historical domain facts its primary state model.


Audit logging: history is retained, but usually remains secondary

A system can supplement CRUD with an audit log. When the canonical client row changes, the system also writes an entry such as:

TimestampActorActionBeforeAfter
2026-04-12 14:03Gate G-7Updated email for C-204contact@...data@...

The audit entry may record a human user, an AI agent, a service, an approval identifier, an IP address, timestamps, and other evidence. It can be created by application code, database triggers, a security product, or a separate auditing service.

Audit logging’s source of truth

In the common pattern, the current CRUD table remains the source of truth. The audit log exists to answer questions such as:

  • Who changed this record?
  • What was the prior value?
  • When did it change?
  • Was the action permitted?

The log is valuable evidence, but the application normally does not rebuild the canonical client table by replaying it. If the audit log and canonical table disagree, operational policy will usually treat the current table as authoritative.

Audit logging’s update semantics

The substantive operation remains an in-place update:

  1. Update the canonical row.
  2. Record evidence that the operation happened.

The two writes might be committed atomically in one database transaction, which is much safer than writing the audit record later. But even a complete and trustworthy audit history does not automatically make a system event-sourced.

The defining Event Sourcing commitment is stronger:

Every meaningful state change is represented by a stored event, and the authoritative state can be reconstructed by applying those events.

An audit record often says that a technical operation occurred: “row updated,” “field changed,” or “user edited profile.” An event-sourced domain event should express a meaningful completed business fact, such as VerifiedClientEmailAccepted or ClientAddressChangeApproved.

This short segment from CodeOpinion highlights the risk of translating generic CRUD operations directly into generic “events.”

Event Sourcing do's and don'ts

Watch “Event Sourcing do's and don'ts” from CodeOpinion for a concise explanation of why an event should capture the business reason for a state transition, not merely label an update operation.

Watch the CRUD sourcing discussion. Focus on the contrast between a vague event such as “product quantity updated” and a meaningful event such as “inventory adjusted.” Apply the same test to client data: an approved, evidence-backed legal-name change says more than “client updated.”

An audit log may contain rich context too, and some systems deliberately make audit entries replayable. At that point, the boundaries can blur. The decisive question remains: is the log merely evidence about a separately authoritative current-state database, or is it the authoritative history from which state is derived?


Record versioning: preserve prior states, not necessarily domain transitions

Record versioning preserves older versions of a record when a change occurs. This is common in temporal tables, document revision systems, and “slowly changing dimension” designs used in data warehousing.

Rather than overwriting the old value and losing it, the system may close the old version and store a new one.

A temporal-table-style view: the current item-value table is kept separately from historical versions, where each earlier value has a start and end period. An update or deletion moves the prior version into history rather than making it disappear.

For a client email, a versioned representation could be:

Client IDEmailValid fromValid to
C-204contact@northwind.example2026-01-012026-04-12
C-204data@northwind.example2026-04-12Current

This architecture can answer: What email did we have recorded for this client on 1 March? It may also enable an audit-like comparison of versions.

Record versioning’s source of truth

The authoritative data is usually the current version, or the set of record versions managed as a versioned state store. The history is made of prior states of the record.

If the current row is lost, a system may be able to select the latest version from the version history. So record versioning can be durable and reconstructable in a limited sense. But its core model is still usually “the client record at revision 7,” not “the domain facts that caused revisions 1 through 7.”

Record versioning’s update semantics

A change means replacing one state version with another:

  1. Preserve or close the old record version.
  2. Create a new record version containing the new state.
  3. Treat the newest applicable version as current.

The historical entry might show that a client’s email changed. It may not say why it changed, what evidence supported it, what exact gate evaluated it, or whether the change represented a correction, a merger, a verified contact update, or a temporary administrative workaround.

Those details can be added as metadata. But adding history and metadata still does not make versioning Event Sourcing unless the domain events, rather than record versions, are authoritative.

Version history versus event history

The difference is easiest to see in what each stored item means:

PatternTypical stored historical itemMain question it answers
Record versioning“This was the client record during this period.”What did the record look like then?
Event Sourcing“This business fact happened at this point.”What happened, in what order, and what state follows?

A versioned record is generally a snapshot of state. An event is generally a fact about a transition.


Event Sourcing: the event stream is authoritative

In Event Sourcing, the source of truth is the ordered event stream. A canonical-client table may still exist, but it is a projection: a durable, useful representation derived from the stream.

Consider a single approved email change.

ArchitectureAuthoritative writeWhat updates canonical email?
CRUDOverwrite canonical_email in client rowThe update operation itself
CRUD plus auditOverwrite client row and record audit entryThe update operation itself
Record versioningInsert new client-record versionSelecting the latest version
Event SourcingAppend an approved domain eventA projector applying that event

In your target workflow, an event-sourced history might contain facts conceptually like:

  1. An AI agent proposed a new contact email, with evidence and provenance.
  2. An acceptance gate evaluated the proposal.
  3. The gate accepted the proposal.
  4. A domain event recorded that an approved client-email change took effect.

The canonical client projection would be designed to react only to the event carrying the necessary authority. It would ignore the mere existence of a proposal.

Event Sourcing’s update semantics

A change does not mutate historical events. The system appends a later event.

If an earlier approved email is found to be wrong, the historical event remains. A later correction event records the new fact, and the projector calculates the new current state by applying the full sequence.

The Azure Architecture Center puts the principle plainly: persistent event data should not be edited; correction is normally represented through a compensating event.

Event Sourcing pattern - Azure Architecture Center

Read this Azure Architecture Center section to reinforce the practical consequence of immutability: correcting the present result does not require pretending an earlier recorded fact never existed.

In “Versioning events,” read the explanation of compensating events. For this course, focus on the architectural principle rather than the later schema-evolution techniques.

This does not mean an event-sourced system cannot have a current-state database. It usually should, especially when applications need fast client lookups. The distinction is authority:

  • In CRUD, the client table is normally authoritative.
  • In Event Sourcing, the client table is derived and rebuildable; the event stream is authoritative.

A practical classification test

When reviewing a proposed architecture, use this sequence of tests.

Test 1: If the canonical client table vanished, what rebuilds it?

  • If the answer is “restore the latest database backup,” you likely have CRUD.
  • If the answer is “use the change log if possible, but the table is the official record,” you likely have CRUD plus audit logging.
  • If the answer is “select the most recent version of each record,” you likely have record versioning.
  • If the answer is “replay the ordered domain events through a projector,” you have Event Sourcing.

Test 2: What does the stored history mean?

  • “The profile was edited” suggests an audit operation.
  • “This was the profile at version 12” suggests record versioning.
  • “A verified address change was accepted after gate G-7 approved proposal P-81” suggests a domain event.

Test 3: How are corrections represented?

  • Overwrite the current field: CRUD.
  • Overwrite it and add an audit row: CRUD plus audit logging.
  • Create a later record version: record versioning.
  • Append a correction or compensating domain event: Event Sourcing.

Test 4: Does the history control current state?

This is the decisive one.

An event log is Event Sourcing only when the authoritative current state is obtained by applying the event history. If the system updates the canonical table directly and logs something afterward, it is an audited CRUD system, even if the log is append-only.


Choosing carefully for the client-update use case

All four approaches can support a gated AI-assisted client-data workflow. The question is what you need the system to explain and reconstruct.

A conventional canonical database with an append-only proposal ledger may be enough when:

  • the canonical record is clearly the authority;
  • the main requirement is a traceable review history;
  • replaying historical business decisions is not a core capability;
  • simpler operational behavior is more valuable than a fully event-sourced model.

Event Sourcing becomes more compelling when you need the history of accepted decisions themselves to be authoritative, replayable, and useful for multiple derived views. Examples include rebuilding the canonical client view, reproducing what a gate decided at the time, constructing review dashboards, and investigating how a client’s canonical profile evolved.

Neither choice removes the need for governance. An append-only record does not automatically satisfy privacy, retention, access-control, or deletion obligations. Those requirements will be addressed later in the course.


Key takeaways

CRUD, audit logging, record versioning, and Event Sourcing can all preserve useful information, but they make different records authoritative and treat updates differently.

  • CRUD makes the latest record authoritative and usually overwrites fields in place.
  • Audit logging supplements an authoritative current-state system with evidence of operations; it is not automatically replayable state.
  • Record versioning preserves earlier snapshots of record state, making historical-state queries possible.
  • Event Sourcing makes ordered domain events authoritative; projectors derive current state, and corrections are appended as later facts rather than rewriting history.

For the AI-proposal architecture, the crucial design rule remains: a proposal and its review history may be retained in any pattern, but canonical state must change only through the defined acceptance authority.

Next, you will begin modeling the workflow’s artifacts precisely: distinguishing commands, proposals, domain events, and derived read models.

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

Sign up