A checkpoint records the last successfully processed position in an event stream. When a subscription restarts — whether after a planned shutdown or a crash — it loads its checkpoint and resumes reading from that position rather than from the very beginning. Without checkpoints, every restart would replay the entire event history, making long-running projections impractical.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Eventuous/eventuous/llms.txt
Use this file to discover all available pages before exploring further.
The Checkpoint type
A checkpoint is a lightweight value type:
| Member | Description |
|---|---|
Id | Matches SubscriptionOptions.SubscriptionId; used as the document/row key in the store |
Position | Last committed global or stream position; null means “start from the beginning” |
IsEmpty | true when Position is null |
Checkpoint.Empty(id) | Creates an initial, position-less checkpoint |
ICheckpointStore
Any persistent backend can be used as a checkpoint store by implementing two methods:
GetLastCheckpoint— called once at startup; returnsCheckpoint.Emptywhen no record exists yet.StoreCheckpoint— called byCheckpointCommitHandler; theforceflag bypasses any batching and writes immediately (used at shutdown or on errors).
NoOpCheckpointStore
For ephemeral subscriptions that do not need to persist progress — such as integration tests or transient catch-up reads — use NoOpCheckpointStore:
start (the constructor argument) or from the beginning if start is null. It also fires an optional CheckpointStored event that is useful in tests for asserting progress.
MongoCheckpointStore
The MongoDB implementation stores one document per subscription in a dedicated collection:
MongoCheckpointStoreOptions
BatchSize and BatchIntervalSec reduces write pressure on MongoDB at the cost of replaying more events after an unclean shutdown.
How checkpoints are committed
Checkpoints are not written after every single event.EventSubscriptionWithCheckpoint<T> uses a CheckpointCommitHandler to buffer commit positions and flush them in the background:
CheckpointCommitHandler uses CommitPositionSequence — a sorted set — to track in-flight positions. It will only advance the committed position to the highest consecutive sequence number without gaps. If events arrive out of order (as they do with PartitioningFilter), the handler waits until the gap is filled before writing a new checkpoint.
| Tuning option | Location | Default |
|---|---|---|
| Batch size | SubscriptionWithCheckpointOptions.CheckpointCommitBatchSize | 100 |
| Commit delay | SubscriptionWithCheckpointOptions.CheckpointCommitDelayMs | 5 000 ms |
Registering a checkpoint store
Subscription-scoped store
The most common approach — attach the store to a single subscription using.UseCheckpointStore<T>() on the builder:
SubscriptionId, so different subscriptions can use different stores independently.
Application-wide store
To share a single store instance across all subscriptions, register it globally:In-memory store (testing)
For tests or transient subscriptions, skip persistence entirely:When
EventuousDiagnostics is enabled (the default in development), Eventuous automatically wraps the checkpoint store in a MeasuredCheckpointStore that records OpenTelemetry metrics for checkpoint load and store operations.