Event sourcing

Most ledgers keep the latest balance and a log they hope agrees with it. LedgerTM keeps the events and derives the balance.

Every balance has a history
Events in, state and views derivedA stream of events on the left is the system of record; current state, projections, a time machine and the books are all derived from it.OpenedAdvanced 40mInterest accruedRate changed, value-datedEvent stream: the system of recordCurrent statederived, never editedProjectionsscreens, lists, statementsTime machineany date, as it was known thenBooksjournals from the same events
The stream is the record. Everything else is a view of it.

Nothing is overwritten.

Every movement, correction and decision is an event with a trading date, a value date and an author. State is computed from the events, so the audit trail is not beside the system of record. It is the system of record.

Before and after
SituationA conventional ledgerLedgerTM
A rate change effective last monthAdjust balances by hand, note it somewherePost the change with its value date; the engine re-accrues and posts the difference as new events
"What did this account look like on 31 March?"Restore a backup, or trust a reportReplay to 31 March: both what was true then and what was known then
A new report nobody planned forWait for the next releaseBuild a new projection over the whole history, retroactively
The auditor asks who changed thisSearch the log, hope it matchesRead the event: who, when, on whose authority, what it changed
A future-dated payment instructionA batch job with its own rulesAn event that applies when the business clock reaches its value date
Commands in, queries out

Every write is a command. Every read is a query. Nothing is both.

A command is handled against one aggregate, which decides and emits events. A query reads a read model that was projected from those events. A message declares which it is through a marker interface, the build checks the declaration, and a read never touches an aggregate. The name for this is CQRS, and the engine uses it all the way through, not for a slice of it.

Aggregates decide

One per thing with a history: an account, a counterparty, a structure, a payment. Verbs, invariants, events. No reads served from here.

Read models serve

Lists, details, statements, dashboards, each shaped for its screen and rebuilt from the events when the shape changes. About eighty of them.

Why it matters

Writes stay small and auditable. Reads stay fast and disposable. A new screen is a new projection, not a change to the model.

Forecast and day-end are one path

The forecaster runs the same code as tonight's day-end.

Project an account to maturity and you see exactly what the day-end will post, day by day. A test proves the two stay in parity.

Events answer "when did we know". Dated properties answer "when was it true". The two together are the model.

What this means for you: a correction is a new event, not a data fix. The number you show a regulator is reproducible from the stream, months later, to the cent.