Snapshots and Performance¶
This guide explains how to use snapshots in event-sourced systems to improve performance and reduce overhead during replay. While EventSourcingDB treats all events as immutable and equally important, applications can introduce snapshots as a way to avoid rebuilding state from the beginning of a stream every time. This is especially useful for aggregates with long histories or systems with high throughput.
Snapshots are not a native concept in EventSourcingDB — there is no special snapshot type or storage mechanism built into the database. Instead, snapshots are represented as ordinary events that follow the same structure and guarantees as any other event. This simplicity allows you to define, write, and consume snapshots using the same tools and APIs you already use for regular events.
Why Snapshots Matter¶
In an event-sourced system, the current state of an entity or aggregate is typically reconstructed by replaying its entire event history. This works well for short streams, but becomes inefficient as the number of events grows.
For example, rebuilding an aggregate with 50 events may take milliseconds — but one with 10,000 events could take much longer. This adds latency to command processing, reduces responsiveness, and increases CPU usage under load.
Snapshots solve this by capturing the derived state at a given point in time. Instead of replaying all events, the application can load the most recent snapshot and replay only the events that occurred afterwards. This reduces the cost of reconstruction and makes performance predictable.
Modeling Snapshots as Events¶
In EventSourcingDB, a snapshot is just an event — typically with a special event type such as:
The snapshot contains a complete representation of the current state in its data field. It can be written at any point, usually after a fixed number of domain events, or when the application detects a significant state change.
Snapshots must include the same subject as the stream they refer to. This ensures that they are ordered correctly and replayed in context with the rest of the stream.
Because EventSourcingDB does not treat snapshot events differently, your application is responsible for:
- Choosing when to create a snapshot
- Ensuring that the snapshot is a valid representation of prior events
- Deciding how to identify and load the most recent snapshot
This flexibility allows you to design snapshot logic that fits your domain and performance requirements — without introducing special-case behavior in the database.
Creating and Writing Snapshots¶
The process for creating a snapshot usually looks like this:
- Rebuild the aggregate by replaying its events as usual
- Serialize the current state into a snapshot object
- Write the snapshot to EventSourcingDB using a dedicated event type
- Optionally tag the snapshot with metadata, such as version or timestamp
You can use the same write API as for any other event, including schema validation if desired. Snapshot events typically appear less frequently than domain events, so they are easy to manage and analyze.
Reading Snapshots During Replay¶
To take advantage of snapshots during replay, the application must:
- Read the most recent snapshot for the subject
- Restore the state from the snapshot
- Read all subsequent events and apply them incrementally
This requires the application to distinguish snapshot events from domain events. A common pattern is to filter by event type prefix or suffix, or to tag snapshot events with a known schema.
Since all events are ordered by their global id, it is easy to find the point in the stream after which the remaining events need to be applied. EventSourcingDB ensures that this ordering is strict and stable, which simplifies the logic for partial replays.
EventQL can also be used to query for the latest snapshot using ORDER BY e.id DESC TOP 1.
Performance Considerations¶
The use of snapshots significantly reduces the time needed to rebuild aggregates or read models — especially when combined with other performance strategies:
- Keep snapshot intervals balanced: too frequent increases storage; too rare increases replay cost
- Use simple, flat structures in snapshot
datafields for fast deserialization - Avoid including redundant or computed fields that can be derived from events
- Compress large snapshots if necessary (application-side)
- Create snapshots asynchronously if synchronous writes add latency
EventSourcingDB is optimized for sequential access and streaming, so performance is generally consistent. Still, reducing the number of events that must be loaded and processed is often the most effective way to improve end-to-end performance.
Snapshots Are Optional, but Useful¶
Not all systems need snapshots. For short-lived entities or infrequently accessed aggregates, replaying from the beginning may be acceptable. But as your system grows, and certain streams accumulate thousands or millions of events, snapshots become a critical tool for keeping replay fast and resource usage predictable.
By modeling snapshots as regular events and handling them at the application level, you retain full control — without compromising the consistency, traceability, or semantics of the event stream.