Alpha Version: You are viewing the ALPHA documentation. This is an experimental version and may contain breaking changes.
Skip to main content

Local Persistence for the Local Platform

By default the local platform wipes all state on restart. If you are iterating on a UI, demoing a workflow, or replaying events across multiple dev sessions, you can opt into a SQLite-backed persistence layer that survives restarts without running a separate database server.

Jest tests continue to use the pure in-memory path — persistence is strictly opt-in.


Two ways to enable SQLite

Option 1 — Platform functor argument

module Platform = InMemory.Platform.MakeWithConfig({
let silent = false
let splitApi = true
let cloner = false
let backend = Backend.Sqlite({
path: "./.reventless/local.db",
resetOnStart: false,
})
})

Pass resetOnStart: true to wipe the file every time Platform.MakeWithConfig runs — matches the fresh-every-time behaviour that Jest relies on. Leave it false for dev sessions where you want data to accumulate across restarts.

Option 2 — Environment variable

REVENTLESS_LOCAL_BACKEND=sqlite:./.reventless/local.db pnpm dev

The default Platform.Make() picks up REVENTLESS_LOCAL_BACKEND via Backend.fromEnv() — no code change required. Recognised values:

ValueEffect
unset, empty, or memoryPure in-memory (default)
sqlite:<path>SQLite file at <path>, no reset
sqlite:<path>?resetSQLite file at <path>, wiped on each construction

Verifying the active backend

On startup makePlatform logs which backend is in use:

[Platform] backend: memory
[Platform] backend: sqlite (./.reventless/local.db)
[Platform] backend: sqlite (./.reventless/local.db, resetOnStart)

Inspecting the local database

SQLite writes one file at the configured path. You can poke at it with the standard CLI:

sqlite3 ./.reventless/local.db
sqlite> .tables
event_log qdb_Orders qdb_Products
sqlite> SELECT * FROM event_log LIMIT 5;
sqlite> SELECT partition_key, item FROM qdb_Orders LIMIT 5;

The schema is:

  • event_log(log_name, aggregate_id, seq_nr, payload, PRIMARY KEY(log_name, aggregate_id, seq_nr))
  • qdb_<name>(partition_key, sub_key, item, PRIMARY KEY(partition_key, sub_key)) — one table per QueryDb

Delete the file to reset everything. Committing a sample local.db into a fixtures folder is a reasonable way to share a deterministic demo dataset with collaborators.


What is persisted

All five storage surfaces are SQLite-backed:

SurfaceStatus
EventLogpersistent
QueryDb (basic load/save/delete)persistent
DcbEventLog (events + tags + conditional append)persistent
TaskBucket (put / get helpers; bucket maker still returns dummy resource)persistent
QueryDb GSI indexes (json_extract-based SQLite indexes)persistent
QueryDb TTL (expires_at column + lazy filter)persistent

A restart with Backend.Sqlite({path, resetOnStart: false}) keeps all of the above intact. Use resetOnStart: true (or just delete the file) to start fresh.