Technical explanations · Drawbly
Event sourcing: replay four events to find the seats left
By Drawbly ·
In event sourcing, the durable record is a sequence of facts about what happened. The current value is derived from those facts. A small seat-reservation example makes the difference visible: when someone cancels, we append a cancellation event instead of rewriting the earlier reservation.

A workshop with eight seats
Workshop W-17 starts with eight seats. Its event stream is ordered by version for this workshop. These names and counts are fictional; they are just enough to follow the state change.
- v1 · SeatsOpened(8). Available: 8.
- v2 · SeatsReserved(R1, 2). Reservation R1 holds two seats. Available: 6.
- v3 · ReservationCancelled(R1). The cancellation refers to R1, so the projector releases its two seats. Available: 8. Version 2 stays in the stream.
- v4 · SeatsReserved(R2, 3). A second reservation holds three seats. Available: 5.
A read model needs more than a running total here. It must remember that R1 held two seats, otherwise the cancellation does not tell it how many to restore. In this tiny example, start with capacity = 0 and an empty map of active reservations. Apply each event in order; on cancellation, look up the reservation ID, remove it, then compute available = capacity - sum(active reservations). After v4, R2 holds three of eight seats, leaving five. A real system also defines what happens for duplicate, missing or already-cancelled reservation IDs.
What does replay rebuild?
The append-only event stream is the source of this workshop's state. A projector can consume it to build a fast read model such as “five seats left.” If that read model is lost or its calculation changes, replay v1 through v4 into a fresh projection to rebuild it. Replaying only through v2 gives the historical result of six seats available. This ability to reconstruct a point-in-time state is why the old reservation is retained.
Reads from an asynchronous projection may briefly lag behind a newly appended event. Do not promise that a page showing five seats can safely accept five simultaneous reservations. The command side must check current aggregate state and enforce capacity when it appends events. The read model is convenient for queries; it is not, by itself, a concurrency guard.
A request is a command; a stored fact is an event
“Reserve seven seats” is a command: a request that can be rejected. SeatsReserved(R3, 7) would be an event: a statement that the reservation actually happened. With five seats available after v4, this command is rejected and no success event is appended. If two callers both try to reserve the last seats, use a per-workshop expected version or equivalent optimistic concurrency control so both cannot commit from the same stale state. Retry a conflict by rereading the stream and reevaluating the command; do not blindly append the old decision.
An event store is not the same thing as a message broker. The store must support reading this workshop's ordered history and safe appends. A broker can distribute events to projectors and other consumers, but delivery may be duplicated or delayed. Make projection handlers safe to repeat and track their position. The webhook versus polling guide shows why delivery and recovery need their own design.
When is event sourcing worth the cost?
It can be useful when the history and reasons for changes matter, or when you need to rebuild different views from the same facts. It brings extra work: event schemas must remain readable as the software evolves; old events cannot simply be edited away; large streams may need snapshots; read models need lag and replay monitoring. For a small application that only needs its current value, a normal row update and an audit log can be simpler.
Keep replay separate from external side effects. Rebuilding a seat-count view must not send another confirmation email or take another payment. If a system publishes integration events after a database write, the idempotency example explains one duplicate-write hazard; publication reliability is another design decision. Event sourcing does not automatically give exactly-once effects across other systems.
Draw the stream you actually have
Open the editable Drawbly diagram. Replace the workshop and reservation names with one entity in your system. Label the ordered events and the read value after each. If an event reverses an earlier action, show both facts; the point of the drawing is to explain how the current value follows from the full history.
Microsoft Azure Architecture Center: Event Sourcing pattern covers streams, projections, replay, event design and concurrency. AWS Prescriptive Guidance: Event sourcing pattern discusses point-in-time reconstruction, eventual consistency and operational costs. Martin Fowler: Event Sourcing describes replay and the risk of repeating external side effects. The workshop example is original and fictional.