Expected version matches — append accepted
Expected version is stale — conflict
Expected-version checking rejects an append when the stream has changed.
Command
Domain decision
Domain event
Event store
Projection
A command reaches the application → the application applies domain rules and produces events → Chronacta appends them to a stream → projections build read models for queries.

The write path

Receive the command, load the aggregate, invoke its behavior, and append the resulting events with an expected version.

Do not record a successful external operation before it has succeeded. For example, requesting payment and recording payment authorization are different steps.

Optimistic concurrency

If another append has changed the stream version, the write is rejected. Reload the aggregate and re-evaluate the command, or report the conflict.

The version check detects a conflicting write. Domain invariants determine whether the command is valid against the new state.

Idempotency

A timeout does not tell the client whether an append committed. Retry the same append with the same idempotency key and payload according to the API contract.

Append idempotency is not the same as command idempotency. A command handler must also account for repeated business requests and external side effects.

Common errors

Do not make a domain decision from a lagging read model when it requires current aggregate state. Do not omit the expected version merely to avoid conflicts.

Do not rerun command handling during event replay. Reconstructing recorded state and deciding on a new command are separate operations.

Practical exercise

Handle two commands against the same loaded version. Verify that only one conflicting append succeeds, then reload and decide how the other command should be handled.

Event Sourcing learning path · Previous · Next · Chronacta documentation