SQLite snapshot store
Ce contenu n’est pas encore disponible dans votre langue.
SqliteSnapshotStore persists snapshots to a SQLite file —
durable, zero-dependency on Bun, peer-dep on Node. Pair with
SqliteJournal for the
standard single-node production setup.
import { SqliteJournal, SqliteJournalOptions, SqliteSnapshotStore, SqliteSnapshotStoreOptions, ActorSystem, ActorSystemOptions,} from 'actor-ts';
const sqliteJournalOptions = SqliteJournalOptions.create() .withPath('/var/lib/my-app/events.db') .withWal(true);const sqliteSnapshotStoreOptions = SqliteSnapshotStoreOptions.create().withPath('/var/lib/my-app/snapshots.db');const actorSystemOptions = ActorSystemOptions.create().withPersistence({ journal: new SqliteJournal(sqliteJournalOptions), snapshotStore: new SqliteSnapshotStore(sqliteSnapshotStoreOptions),});const system = ActorSystem.create('my-app', actorSystemOptions);Configuration
Section titled “Configuration”type SqliteSnapshotStoreOptions = { path?: string; // file path, or ':memory:' snapshotsTable?: string; // default 'snapshots' keepN?: number; // max snapshots kept per persistenceId, pruned on save (default 3) busyTimeoutMs?: number; // lock-wait budget, default 1000; 0 = fail fast driver?: SqliteDriver;};path, busyTimeoutMs and driver behave exactly as they
do on the SQLite journal —
including the reason busyTimeoutMs has a framework-set
default at all: the drivers ship different ones (0 ms on
bun:sqlite and node:sqlite, 5000 ms on better-sqlite3),
and the wait is synchronous, so it blocks the event loop.
There is no wal option here; instead the snapshot store
adds keepN — the maximum number of snapshots retained
per persistenceId, with older ones pruned on each save
(default 3).
const sqliteSnapshotStoreOptions = SqliteSnapshotStoreOptions.create() .withPath('/var/lib/my-app/snapshots.db') .withBusyTimeoutMs(1000);new SqliteSnapshotStore(sqliteSnapshotStoreOptions)Schema
Section titled “Schema”CREATE TABLE snapshots ( persistence_id TEXT NOT NULL, sequence_nr INTEGER NOT NULL, payload TEXT NOT NULL, timestamp INTEGER NOT NULL, PRIMARY KEY (persistence_id, sequence_nr));Same pattern as the journal: keyed by
(persistence_id, sequence_nr). The framework reads the
highest sequence_nr for a given persistence_id on
loadLatest.
Pairing with the journal
Section titled “Pairing with the journal”// Production:{ const sqliteJournalOptions = SqliteJournalOptions.create().withPath('/var/lib/events.db'); const sqliteSnapshotStoreOptions = SqliteSnapshotStoreOptions.create().withPath('/var/lib/snapshots.db'); journal: new SqliteJournal(sqliteJournalOptions), snapshotStore: new SqliteSnapshotStore(sqliteSnapshotStoreOptions),}The journal and snapshot store are independent files. You can also put them in the same file with different table names — but two files keep operations simpler (back up independently, vacuum independently).
For multi-node deployments where the journal is Cassandra, you can still use SQLite for snapshots if each entity always recovers on the same node. But for sharded entities (which move between nodes), the snapshot store also needs to be shared — see Object storage snapshot store.
Performance
Section titled “Performance”- Snapshot write — single INSERT, ~100 μs. Dominated by serialization, not SQLite I/O.
- Snapshot read — single SELECT, sub-millisecond.
For very-large snapshots (multi-MB state), serialization is the bottleneck. Consider compression (Object storage compression) or a different snapshot strategy.
Where to next
Section titled “Where to next”- Snapshots — the policy + mechanics.
- SQLite journal — the journal you pair this with.
- In-memory snapshot store — for tests.
- Cached snapshot store — read-through cache.
The SqliteSnapshotStore
API reference covers the full options.
