Skip to content

Storage Backends

Document-store separates writes from reads. The persistence layer handles writes — storing documents, rendering the latest state, and maintaining the change log for sync. For reads, you query your database directly.

Supported backends

BackendBest forPackage
SurrealDBEmbedded or distributed, multi-model queriessurrealdb + @surrealdb/node
SQLiteDesktop apps, CLI tools, simple embeddedbetter-sqlite3
MongoDBServer deployments, large datasetsmongodb

How storage works

The persistence layer manages three concerns:

1. Change log

Raw CBOR documents for P2P sync. Every add() and edit() is logged here. Peers exchange these during sync.

2. Document store

Internal document state — used by the store to compute edits and validate writes.

3. Rendered tables

The latest version of each document, ready for your app to query. One table/collection per document type. This is what you read from.

add('bookmark', { uid, url, title })

    ├──► change log      (CBOR for sync)
    ├──► document store  (internal state for edits)
    └──► bookmark  ◄── your app reads this

Choosing a backend

SurrealDB is the recommended default. The embedded SurrealKV engine is file-backed with no server to manage — same deployment simplicity as SQLite, but with a much richer query language. Relations, graph traversals, record links, full-text search, and native binary types. Scales from embedded to distributed without changing your queries.

SQLite if you want the simplest possible setup or need raw SQL compatibility. Single file, synchronous API, battle-tested. Good for CLI tools and small apps where you don't need relational queries across document types.

MongoDB if you're running a server with multiple users or need horizontal scaling. Use the MongoDB driver directly for reads.

Something else? See Custom Backend for how to write your own persistence layer.