Skip to main content
Meridian delegates all persistence to the meridian-storage crate, which exposes two traits:
  • Store<V> — CRDT snapshot storage (get / put / delete / scan)
  • WalBackend — append-only Write-Ahead Log (append / replay / truncate)
All built-in backends are feature-gated. Pick the one that matches your deployment.

Built-in backends

sled (default)

Embedded key-value store. Zero infrastructure, single binary. Best for single-node deployments.

PostgreSQL

Fully managed, horizontally scalable. Requires a Postgres 14+ instance.
Meridian runs CREATE TABLE IF NOT EXISTS + CREATE INDEX IF NOT EXISTS on startup — no manual migration needed. Schema created automatically:

Redis

Uses Redis for snapshots (GET/SET) and Redis Streams for the WAL (XADD/XRANGE/XTRIM).

S3 WAL archive

Enable durable off-node WAL backups with the wal-archive-s3 feature. Works with AWS S3, Cloudflare R2, and any S3-compatible store (MinIO, LocalStack).
Set S3_BUCKET to opt in — no other change required:
How it works
  • Upload on threshold — every WAL_SEGMENT_SIZE appends, the accumulated segment is uploaded to S3 as {prefix}{seq_start:020}-{seq_end:020}.msgpack.
  • Upload on truncation — before local WAL entries are truncated (compacted), any pending unarchived entries are flushed to S3. This guarantees data is on S3 before local deletion.
  • Restore on startup — if the local WAL is empty (fresh node or wiped disk), all S3 segments are downloaded and replayed in order before the server accepts connections.
  • Non-fatal uploads — S3 upload failures are logged as warnings. The local WAL remains authoritative and writes are never blocked.
Minimum IAM policy

WAL replay and point-in-time recovery

Every write goes through the WAL before being applied to the snapshot store. On restart:
  1. The server loads CRDT snapshots directly from the store (already up-to-date).
  2. WAL entries written after the last compaction are replayed to catch up.
To replay entries up to a specific point in time:
The WAL compactor runs every 60 seconds and truncates entries older than the current snapshot checkpoint, keeping the WAL bounded.

Custom backend

Implement Store<V> and WalBackend for any storage engine:
Pass your implementation to server::run():

Contract