Skip to main content
By default the SDK holds all CRDT state in memory — a page refresh clears everything and the client re-syncs from the server. Enabling persistence changes this: CRDT values are cached in IndexedDB and restored instantly on the next load, before the WebSocket connects.

Setup

waitForRestore() resolves once all IndexedDB reads triggered by handle creation have completed. Call it after declaring every handle you need, not before.

How it works

On reconnect the server sends a Sync delta that merges authoritatively on top of the cached state — the cache is never stale for long. The visibilitychange flush covers most crash and background-kill scenarios: when the browser moves a tab to the background (mobile app switch, tab minimise) the queue is persisted immediately, before the process may be suspended or killed.

Offline mode

Pass offline: true to never auto-connect. The client operates entirely from the local cache. Call client.connect() explicitly when you want to go online.

Custom storage adapter

Both StateStorage (async) and SyncStateStorage (sync) are plain interfaces — implement them to use any backend:

Storage adapters

Multi-tab sync

Pass tabSync: true to keep all open tabs in the same namespace in sync instantly — without each tab waiting for its own server round-trip:
When Tab A receives a server delta it broadcasts the raw delta bytes to every other tab sharing the same namespace via the BroadcastChannel API. Tab B applies the delta immediately to its local CRDT handles — the same delta will also arrive via Tab B’s own WebSocket subscription, but re-applying it is safe because all CRDTs are convergent. This is especially useful when Tab B is temporarily disconnected or backgrounded: it receives updates from Tab A without needing connectivity of its own.
BroadcastChannel is available in all modern browsers and in Node.js 18+. The SDK checks typeof BroadcastChannel !== "undefined" at construction time and silently skips tab sync if the API is absent.

Caveats

  • Awareness — ephemeral by design. Offline updates are dropped silently since awareness data is time-sensitive and not persisted.
  • SSR / Node — indexedDbStateStorage rejects gracefully if indexedDB is not available. localStorageSyncOpsAdapter is a no-op if localStorage is unavailable.
  • Token rotation — snapshot keys include the client_id from the token. If you issue a new token with a different client_id, the previous cache is ignored (not deleted automatically).
  • Long offline sessions — the server GCs RGA and Tree tombstones after 24 hours (configurable via MERIDIAN_CRDT_GC_GRACE_MS). Clients offline longer than this grace period may not receive delete deltas for GC’d tombstones on reconnect.