An adapter is a concrete store: it implements the RawEventStore + WakeSource
ports (see Hexagonal Architecture) and everything else —
repository, subscriptions, snapshots, backup — comes from mnesis-store for free.
mnesis ships three.
The primary on-device store. fjall is an embedded LSM-tree engine, so this is a single-process, file-backed store — no server, ideal for IoT, mobile, and desktop.
let store = FjallStore::builder(path).open()?.into_store();- Implements
RawEventStore,WakeSource, and (behind features)SnapshotStore(aggregate and projection state),AtomicAppend, andStreamLister. - Zero-copy reads: the workspace pins fjall with the
bytes_1feature, so thebytes::Bytesinside aPersistedEnvelopeis the same Arc-counted buffer fjall handed back — no copy on the read path. - Event payloads land on a 16-byte boundary on disk, so zero-copy decoders work.
The $all index knob. A produce-and-sync device that never reads $all
should not pay to maintain it. So the $all index is configurable:
FjallStore::builder(path).all_index(AllIndex::Disabled).open()?; // no $all index
// AllIndex::Denormalized (default) maintains a fast $all scan.Denormalized (the default) keeps a full second copy of each event for a
point-read-free $all scan; Disabled drops it entirely for a device that only
appends and syncs. This was a measured trade (≈9.3 MB vs 6.8 MB for 20k events)
— see the principal-engineer rule on surfacing such forks.
A server-side store over PostgreSQL (via sqlx), for when many processes share
one event store. Implements the same ports; the $all ordering is made gap-free
with a reader-side xid8 watermark, and WakeSource is backed by LISTEN /
NOTIFY so live subscriptions work across connections. Choose this when you need
a shared, networked store rather than an embedded one.
InMemoryStore is a full adapter (RawEventStore + WakeSource + SnapshotStore,
plus AtomicAppend/StreamLister behind features) backed by a HashMap. It is
not for production — nothing persists — but it is the fixture mnesis-store's
own tests run against, and the fastest way to exercise a domain end to end without
touching disk.
Because all three implement the same two ports, your domain code, repository,
subscriptions, and backup pipeline are identical across them. Develop against
InMemoryStore, ship on FjallStore, scale to PostgresStore — with no change
above the store construction line. Every adapter is verified against the same
conformance kit, so the contract holds
uniformly.
All three shipped adapters are std — fjall does file I/O, postgres pulls
sqlx + tokio, and in-memory rides mnesis-wake. The kernel and mnesis-store
themselves are no_std, so on a bare-metal device you implement the
RawEventStore + WakeSource ports over your own flash/storage layer and keep the
whole event-sourcing stack. See Embedded & no_std.
The core crates are the frozen 1.0 tier; adapters stay 0.x and may evolve their on-disk layouts (always with a documented export/import migration path). See Stability.
- Writing a Store Adapter — build a fourth.
- Repository — the typed façade over any adapter.
- Backup & Restore — move data between them.