Skip to content
Ledger Consistency: Event-Sourced Ledgers, Immutable Audit Trails, Double-Spend Prevention, Eventual Consistency in Distributed Ledgers

Ledger Consistency: Event-Sourced Ledgers, Immutable Audit Trails, Double-Spend Prevention, Eventual Consistency in Distributed Ledgers

What it is

Ledger consistency is the set of rules that keeps balances, postings, and audit evidence trustworthy under retries, concurrency, failure, and replication. An event-sourced ledger stores authoritative changes as an ordered event log and derives balances into read models; an immutable audit trail preserves who did what without silently rewriting history.

How it works

An append-only event stream records accepted domain facts. A projector consumes those events to build account balances, statements, risk features, and reporting tables. Corrections are new compensating events, and a projection can be rebuilt by replaying the stream.

    stateDiagram-v2
    [*] --> Received
    Received --> Rejected: Validation fails
    Received --> Reserved: Funds check succeeds
    Reserved --> Committed: Ledger command commits
    Reserved --> Released: Timeout or failure
    Committed --> Posted: Projection applies event
    Posted --> Reconciled: External evidence matches
    Posted --> Break: Difference detected
    Break --> Posted: Correcting event applied
    Released --> Received: New authorized attempt
  

The event store is the durable boundary, but consistency depends on what the command handler atomically protects. A database transaction can lock an account row, check available funds, append a posting event, and advance the stream version. This prevents two concurrent requests from spending the same reserved balance within that account aggregate.

BEGIN;

SELECT account_id, available_minor
FROM account_balance
WHERE account_id = $1
FOR UPDATE;

INSERT INTO posting_event (
    event_id,
    account_id,
    business_type,
    amount_minor,
    currency,
    causation_id,
    stream_version,
    payload
) VALUES ($2, $1, 'card_authorization', $3, $4, $5, 1, $6);

UPDATE account_balance
SET available_minor = available_minor - $3,
    stream_version = stream_version + 1
WHERE account_id = $1;

COMMIT;

A unique constraint on the business operation identifier prevents duplicate effects. Version checks prevent an older writer from overwriting a newer state. Authorization of the event itself still belongs in the command path and must not trust client-supplied account ownership.

{
  "event_id": "01J2S4C8M7N6P5Q2R9T0V1W3X4",
  "stream_id": "account_01J1A",
  "stream_version": 128,
  "business_operation_id": "capture_01J2S3",
  "event_type": "ledger.posting.appended",
  "effective_at": "2026-09-24T14:18:31Z",
  "amount": {"minor": 4999, "currency": "USD"},
  "references": {
    "authorization_id": "auth_01J2R9",
    "payment_id": "pay_01J2R7"
  },
  "schema_version": 1
}

Replication can introduce eventual consistency: a replica or projection may lag behind the authoritative stream. Read paths should report the observed version or watermark. A transfer that must not be spent twice belongs in a serialized aggregate or requires a ledger-wide coordination protocol; independent asynchronous replicas alone cannot guarantee that condition.

Tradeoffs

  • Event sourcing — gives complete history and rebuildable views, but requires schema evolution, replay, and correction tooling.
  • Mutable relational balances — gives simple transactional reads, but weakens historical reconstruction unless changes are also recorded.
  • Per-account serialization — makes spend decisions clear, but can create hot accounts and requires deadlock and contention handling.
  • Global serialization — gives one total order, but limits throughput and availability.

When to use

  • Auditors need a replayable history of every accepted and corrected financial action.
  • Retries or concurrent requests could otherwise create duplicate or conflicting postings.
  • Multiple projections need different views of the same facts.
  • Operations span regions or asynchronous services.
  • Business users need to explain a balance from its underlying events.

Alternatives

  • Relational double-entry with audit tables — is conventional and efficient, but does not automatically make every table event-sourced.
  • External consensus ledgers — distribute validation across participants, but add protocol, privacy, and operational complexity.
  • Strict synchronous replicas — reduce stale reads, but trade availability and cross-region latency.

Related