Skip to content

Storage & event log

The server persists through a storage adapter; the production implementation is SQLite inside each folder’s Durable Object. The layout is simple and worth knowing because it explains several behaviors.

  • Document snapshots — current JSON, type, and sequence per document. Reads and doc:init are served from here; nothing is replayed.
  • The document event log — every accepted change, appended as its JSON Patch with its sequence number. This is the document’s history: an audit trail, the source for doc:get-events, and the raw material for future history features (diffs over time, undo, blame).
  • Yjs state and update log — current Yjs binary state per embedded text document, plus its own append-only update log.
  • Reads are O(document), not O(history). Snapshots mean a subscriber’s init cost doesn’t grow with a document’s age.
  • History is first-class. Because changes are stored as patches (not opaque blobs), history is inspectable — by devtools, by audit, by agents — and replayable elsewhere: see Portable event streams.
  • Writes are serialized per folder. One Durable Object, one writer — the storage layer never sees concurrent writes to a folder.
  • The log is the recovery authority. A document’s stored data is, by invariant, equal to the replay of its own event log — snapshots are served for speed but are reproducible, and verify/rebuild/export/import tooling exists against that guarantee. (Even schema migrations applied on read are frozen into the log as ordinary events, so replay never re-derives them.)