Skip to content

System overview

datadata is a library with a clean client/server split. An application talks to it through a session, and two deliberate extension points — the event bus and the storage adapter — decide where and how it runs.

┌────────────────┐
│ session │ the app-facing API:
│ live / staging │ reads, writes, presence
└───────┬────────┘
┌───────▼────────┐ ┌─────────────────┐
│ client │◄───────►│ event bus │ WebSocket / in-process
│ (optimistic │ events │ │
│ overlay) │ └────────┬────────┘
└───────┬────────┘ │
│ ┌────────▼────────┐
│ journal + cache │ server │
│ │ (authoritative) │
┌───────▼────────┐ └────────┬────────┘
│ persistence │ │
│ adapter │ ┌────────▼────────┐
│ (IndexedDB/mem)│ │ storage adapter │
│ optional, │ │ (SQLite / mem) │
│ shared by tabs │ └─────────────────┘
└────────────────┘
  • Session — what the application actually holds. Every read and write goes through one, in one of two kinds: a live session writes straight through, a staging session accumulates a changeset to commit. Both expose the same document API — prepare a document, read it, write it, publish presence — so an app switches lanes without rewriting its call sites. Framework bindings like the React integration hand you a session too.
  • Client — one per connection, shared by the sessions layered on it. Owns subscriptions and the optimistic overlay, and speaks the protocol; a session’s writes land here before they reach the wire.
  • Server — the authority for one folder: validates against schemas, assigns sequence numbers, persists, broadcasts. Enforces limits (document size, rates) and exposes a change callback for automation.
  • Event bus — routes protocol events between clients and server. Implementations: WebSocket (production), in-process (server-side agents, tests, demos), and a composite that combines both on one server.
  • Storage adapter — persistence behind the server: documents, the event log, and Yjs state. The production implementation is SQLite in a Durable Object; tests use memory.
  • Persistence adapter — the storage adapter’s client-side counterpart, and optional: the pending-write journal and the document cache that let a reload replay its writes and render offline. IndexedDB in browsers, memory in tests. Without one the client is memory-only. See offline persistence.

Tabs on the same (folder, principal) namespace share a persistence adapter, so two offline tabs converge with no server round-trip — the only path in this architecture where clients exchange data without the server.

The current production shape is Cloudflare Workers + Durable Objects: one Durable Object per folder, embedding the server, its storage, and its WebSocket connections. The extension points exist precisely so that this is a deployment choice, not an identity — but Cloudflare is the only backend that exists today.