Topic: Where and how savesnapshot/loadsnapshot persist projection state — in-memory dict on the store, or a separate file

Date: 2026-05-29

Time: 08:01

I have enough from the observations to give a complete answer.

How savesnapshot / loadsnapshot Persist Projection State

Short answer: purely in-memory, on a dict hung off the EventStore instance. No file I/O involved.

save_snapshot — writing the snapshot

At eventstore.py:193-199, savesnapshot does this:


def save_snapshot(self):
    if not hasattr(self._store, '_snapshots'):
        self._store._snapshots = {}
    self._store._snapshots[self.name] = {
        "state": copy.deepcopy(self._state),
        "position": self._position,
    }

It lazily creates a snapshots dict on the EventStore instance (self.store), then stores a deep copy of the projection's current state and its position (the last event ID it processed). The dict is keyed by projection name, so each projection gets one snapshot slot.

Key detail: snapshots is not a declared attribute of EventStore — it's monkey-patched onto the instance via hasattr/setattr at line 195-196. The EventStore class itself (lines 28-150) has no knowledge of snapshots at all. This means snapshots live entirely in process memory and are not covered by EventStore.persistevent or loadfromfile, which only handle the event log.

load_snapshot — reading it back

At eventstore.py:202 (and from the grep output at line 204), loadsnapshot reads from the same dict:


def load_snapshot(self) -> bool:
    snapshots = getattr(self._store, '_snapshots', {})

It uses getattr with a default empty dict, restores state and position from the stored snapshot, and returns True if one was found. This is how a new Projection instance pointing at the same EventStore can resume from a prior checkpoint without replaying every event from the beginning — as long as the store object is still alive in memory.

Automatic snapshotting

During catchup() (line 174-182), if a snapshotinterval was configured, the projection auto-saves after every N events:


self._events_since_snapshot += 1
if self._snapshot_interval and self._events_since_snapshot >= self._snapshot_interval:
    self.save_snapshot()
    self._events_since_snapshot = 0

What this means in practice

This is a deliberate simplification — a production system would typically persist snapshots to disk or a database alongside the event log. Here the snapshot mechanism demonstrates the *concept* (skip replaying N events by restoring from a checkpoint) without adding file-format complexity.

Topics to Explore

Beliefs