Go architectures · 3 MIN READ

Event sourcing: state from a durable history

Distinguish a source of truth from ordinary logs and notifications.

Distinguish a source of truth from ordinary logs and notifications. An event-sourced aggregate reconstructs state from accepted domain events. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.

Architecture · A MAP OF THE IDEA

  1. Validate command against current state
  2. Append events at an expected version
  3. Replay events into state

Useful when

  • Temporal reconstruction is a product requirement
  • Domain history must be explicit

Watch out

  • Replay and schema evolution need long-term support
  • External side effects need separate deduplication

Implementation & operation cost: Very high

Fit depends on the task

Small tool or CLI1/5
Domain-rich application3/5
Independent distributed services3/5

Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.

01

The design decision

An event-sourced aggregate reconstructs state from accepted domain events. The event stream is authoritative, so event meaning and ordering must remain interpretable for years. This differs from logging what a conventional database already stored.

02

A complete Go example

Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.

go
package main

import (
	"fmt"
)

type Event struct{ Delta int }

func replay(events []Event) int {
	balance := 0
	for _, e := range events {
		balance += e.Delta
	}
	return balance
}

func main() {
	events := []Event{{Delta: 50}, {Delta: -20}}
	fmt.Println(replay(events))
	fmt.Println(replay(events[:1]))
}

// Output:
// 30
// 50
Read the code

Replaying both events yields 30; replaying the prefix yields 50. The slice only demonstrates deterministic reduction. A real event store also needs append version checks, durable writes, event schemas and a policy for replaying external side effects.

03

Tradeoffs and the simpler alternative

Choose this when temporal history and reconstruction are core requirements. Replay must not resend emails or charge cards. Event evolution, privacy deletion and projection rebuilds are significant costs; an audit table is often enough for a conventional service.

04

Treat event history as a durable contract

An event records a business fact such as OrderAccepted, with identity, aggregate sequence and event schema version. Replaying history applies facts without sending emails or charging cards again. Validate a command against the current aggregate state, decide new events, then append with an expected stream version. A read-then-append sequence without concurrency control can accept conflicting commands. Event sourcing stores state transitions as the source of truth; a message broker alone is not that event store.

05

Plan evolution, snapshots and sensitive data

An old event cannot silently change meaning when a struct is renamed. Use version-aware decoders or explicit upcasting and retain replay fixtures from historical versions. A snapshot is a performance aid tied to a known event sequence, not a replacement for missing history. Avoid embedding secrets and unnecessary personal data in immutable events; deletion and retention obligations need a deliberate design. Do not describe immutable storage as automatically satisfying every audit requirement.

06

Separate replay from external side effects

An event handler updating a projection can be replayed; an external payment requires a durable idempotency key and side-effect policy. Test rebuilding an empty projection from the whole stream and compare state with incremental processing. Test conflicting expected versions and malformed historical events. Adopt event sourcing when historical reconstruction and domain behavior justify its substantial operational cost. An append-only audit log beside ordinary state may solve a simpler audit requirement more cheaply.

TAKE THIS WITH YOU

Rebuilds authoritative state from accepted events. Choose this when temporal history and reconstruction are core requirements. Replay must not resend emails or charge cards. Event evolution, privacy deletion and projection rebuilds are significant costs; an audit table is often enough for a conventional service.

Check your understanding

Which statement best describes Event sourcing: state from a durable history?

Go to the source

Progress stays in this browser. No account needed.