Client config
SyncedDbConfig, the object you hand to new SyncedDb(): connection, local store, log level and sync timings.
SyncedDbConfig is the client-side counterpart to sp00ky.yml. It is passed to new SyncedDb(...) in your app and controls the database connection, where data is cached locally, and how aggressively sync batches its work. Older docs sometimes call it Sp00kyConfig.
Configuration Interface
Example Configuration
Options Detail
database.endpoint
The WebSocket URL for your SurrealDB instance (e.g., ws://localhost:8666/rpc when running locally with the Sp00ky CLI’s bundled dev stack). The Sp00ky client connects directly to the database. Optional, and when omitted the client connects in offline-only mode and queues mutations until a remote is configured.
database.store
'indexeddb'(default): Persistent local storage in the browser'memory': Transient in-memory storage (clears on page reload)
With 'indexeddb', the local store is bucketed per user: each account
gets its own IndexedDB database (sp00ky-<userId>, with a shared
sp00ky-anon bucket for signed-out sessions), and the client switches
buckets automatically on sign-in/sign-out. Cached rows, query state, and the
offline mutation outbox never leak between accounts on a shared device, and
a user’s un-pushed offline mutations resume the next time they sign in. See
Architecture → Per-User Local Buckets.
With 'memory', an auth change resets the store instead (same isolation,
no persistence).
logLevel
Controls the verbosity of logging output:
'trace': Most verbose, includes all internal operations'debug': Detailed debugging information'info': General lifecycle events (connected, synced)'warn': Recoverable errors and warnings'error': Critical failures'fatal': Fatal errors that stop execution
persistenceClient
Determines where small metadata values (the auth token, the stream processor’s persisted state) are stored:
'localstorage'(default): Use browser localStorage'surrealdb': Store in the local SurrealDB instance (inside the current user’s local bucket)- Custom implementation of
PersistenceClientinterface
Note: the boot-time bucket hint (sp00ky:last_bucket) is always written to
plain localStorage regardless of this setting, because the client needs it to pick
the right per-user bucket before any bucket is open.
streamDebounceTime
Window (ms) the client-side Stream Processor uses to coalesce DBSP
stream updates per query before they fan out to useQuery
subscribers, so a burst of synced records (e.g. the initial library
sync) repaints affected views once per window instead of row-by-row.
Lower values feel snappier; higher values reduce re-render thrash on
bursty writes. Defaults to 50.
crdtDebounceMs
Window (ms) used to coalesce CRDT field UPSERTs to upstream. Local
writes are applied to the LoroDoc immediately on every keystroke
(so reload and offline work), but the remote _00_crdt UPSERT is
debounced. Defaults to 500.
refSyncIntervalMs
Base cadence (ms) for the _00_list_ref poll that catches cross-session
UPDATEs that the SurrealDB v3 LIVE-permission gap drops. Defaults
to 500; non-positive values fall back to the default. One cycle reads
every active query’s edges in a handful of round trips (batched by a
row budget, views past 1,000 rows only every 15s), backs off toward 5s
while nothing changes, and never runs back-to-back: the next tick waits
at least as long as the previous cycle took. Statements on the remote
connection run concurrently (up to 6 in flight), so the poll does not
hold registrations or one-shot reads behind it.
persistCircuit
Persist the in-browser stream processor’s store as a snapshot in the local
store, so a reload restores it and only steps in what changed since instead
of re-downloading the working set. Defaults to true under
localEngine: 'sqlite' (the OPFS-backed store holds the bytes) and false
otherwise. Snapshots are written on circuitCheckpointMs (default 30000)
and when the page goes hidden, never per ingest. Without a snapshot the
circuit is primed by reading the cached rows back out of the local store.
circuitProjection
Keep only the fields registered queries evaluate (filter predicates, join
keys, sort keys, plus id/_00_rv) per row inside the in-browser circuit.
Defaults to true. Bodies are rendered from the local store, so the circuit
never needs the rest; on rows with large text fields this is the difference
between a few hundred megabytes of wasm heap and a few megabytes.
allowRawRemote
Opt back in to the raw remote escape hatches (db.useRemote, db.remoteQuery,
db.queryRaw) when the generated schema’s policy.queryAllowlist is warn or
enforce. With the query allowlist on, the SSP
only registers shapes spky generate recorded from the query builder, so a
hand-written SurrealQL string can never be allowlisted; these methods throw
(... is disabled because sync.queryAllowlist is on for this schema) unless
this flag is true. Defaults to false. The gate is client-side only: direct
SurrealDB reads under table PERMISSIONS are unchanged.
Diagnostics
The client exposes a small number of read-only getters intended for e2e regression guards and runtime instrumentation.
pendingMutationCount and subscribeToPendingMutations
Live count of mutations queued for upstream sync. The subscribe variant fires on enqueue/dequeue so a UI can render a “saving…” indicator without polling.
liveRetryCount
Number of times the initial _00_list_ref[_user_*] LIVE SELECT
subscription had to retry on the most recent setCurrentUserId
call. Stays at 0 when the SSP’s pre-emptive per-user table
creation got there first (the default path); a value above 0
means the LIVE registration hit a “table not found” race and the
client fell through to the poll fallback while retrying. The e2e
suite’s z-auth-bootstrap.spec.ts asserts this stays 0 after a
clean signup so the pre-emptive path can’t silently regress.