Event Sourcing in Microservices: Implementing with Akka Persistence

Explore event sourcing in Scala microservices as a way to persist domain facts and rebuild state from event history, with attention to replay cost, projection design, and event evolution.

Event sourcing: Persisting state changes as a sequence of domain events so current state can be reconstructed by replaying those events.

Event sourcing can be powerful in microservices when the history of change matters as much as current state. It is also one of the easiest patterns to over-adopt. The benefit is not “events are modern.” The benefit is a durable log of domain facts that supports audit, replay, and projection models when the domain truly needs them.

The Pattern Stores Facts, Not Just Final State

In a CRUD-style model, the system often stores only the latest state. In event sourcing, it stores a sequence such as:

  • account opened
  • funds reserved
  • funds released
  • address changed

Current state becomes a derived view over those facts.

That can be valuable when:

  • auditability is important
  • replay and projection flexibility matter
  • business logic is naturally event-centric
  • temporal questions such as “how did we get here?” are important

Event Design Quality Matters More Than Framework Choice

The hardest part is not wiring persistence APIs. It is deciding:

  • what counts as a domain event
  • which event fields are stable enough to persist long-term
  • what invariants are enforced before an event is written
  • how projections consume and evolve from those events

Weak event design creates permanent confusion because persisted events are not easy to “just refactor away.”

Replay And Projection Costs Must Be Realistically Planned

Event sourcing usually needs:

  • projection pipelines
  • replay strategy
  • snapshot policy where useful
  • monitoring for lag and rebuild time

Without these, the system can become theoretically elegant but operationally painful. Rebuilding state is only valuable if the recovery and projection process is dependable enough to use under pressure.

Scala Helps With Explicit Event And State Models

Scala is a strong fit when events, commands, and aggregate states are modeled clearly with enums, case classes, and typed transitions.

That helps teams review:

  • valid state transitions
  • event compatibility
  • projection input assumptions
  • replay behavior after schema evolution

The language advantage is not magic persistence. It is stronger modeling at a pattern where modeling quality matters enormously.

Event Sourcing Is Not A Free Replacement For CRUD

It is often the wrong fit when:

  • simple current-state storage is enough
  • history is not especially valuable
  • the domain is unstable and event shapes would churn constantly
  • the team lacks appetite for projection and evolution discipline

In those cases, ordinary persistence plus explicit audit logging may be the better design.

Common Failure Modes

Persisting Technical Events Instead Of Domain Facts

The event stream becomes a log of implementation details rather than stable business meaning.

Ignoring Event Evolution

The system writes events as if schemas will never need to change, then struggles later with replay and compatibility.

Projection Drift

Read models fall behind or become inconsistent, and no one has a reliable replay or repair process.

Practical Heuristics

Choose event sourcing when domain history, replay, and projection flexibility are genuinely valuable. Model events as durable business facts, plan replay and projection operations from the beginning, and avoid using the pattern where ordinary state storage would solve the real problem more simply.

Knowledge Check

Loading quiz…
Revised on Thursday, April 23, 2026