In-process clients
datadata’s client and server are connected by an event bus abstraction, not by a socket. One implementation routes events over WebSockets; another — the in-process event bus — dispatches them as plain function calls within a single JavaScript process.
A real client, no network
Section titled “A real client, no network”connectInProcessClient wires a full client to a full server in the same
process. It is not a mock: the same optimistic-update machinery, the same
validation, the same event ordering — just with microtask latency instead of
network latency.
Server-side agents
Section titled “Server-side agents”The motivating use: an AI agent running next to the server (in the same Durable Object or Node process as the folder’s server) as a first-class client. A composite event bus lets in-process clients and WebSocket clients coexist on one server — so the agent stages edits through an in-process session while humans watch the same live documents from their browsers, each seeing the other’s changes in real time.
The server also exposes change callbacks — onDocumentChange, invoked on every
create, update and delete, onDocumentRestored, invoked on every restore, and
onDocumentsPurged, invoked once per purge — which is how agent-triggering,
auditing, and downstream automation attach without polling. The callbacks are synchronous: long work is started
from one, not awaited in it, and on Cloudflare it goes through the Durable
Object’s runInBackground so the object outlives the event that started it
(see Cloudflare deployment).
They report exactly what reached storage. A write succeeds once it is stored: if a later step fails — telling subscribers, say — the server logs it and recovers the way it would from a dropped message, and the call still succeeds and the callback still fires. A call that rejects stored nothing, so it is always safe to retry, and a mirror or audit log fed from the callbacks never misses a stored write.
Syncing with data outside the folder
Section titled “Syncing with data outside the folder”A folder is the unit of authority — one server owns it and orders its events. Applications routinely need it reconciled with data that lives elsewhere: your main application database, an external API, a system of record that predates the folder.
Getting history out needs no client — that is what portable event streams are for, a one-way replay into another store. Getting changes back in is what needs one. Writes from outside have to enter through a client, so they are validated, ordered and broadcast like anyone else’s.
Where that bridge runs decides what it can see. Outside the folder it connects
over a WebSocket, the same way a browser does — and like a browser it
subscribes per document, so it only learns
about documents it already knew to watch. Inside the folder’s own server
process it can register server.onDocumentChange instead: every document
write in the folder, subscribed or not, with the document in hand. Restores come
through server.onDocumentRestored, which names the document but doesn’t carry
it, so a mirror reads the restored document itself. A
schema migration isn’t one of those writes: a
document is brought forward when it is next read (or, if a client subscribes to
it, right after the schema write), and only the schema change fires the hook, so
a mirror storing document data re-reads that type’s documents when its schema
changes. The folder listings —
sys:index and sys:trash, where renames show up — don’t fire it; a mirror that
tracks them subscribes an in-process client to them, which keeps them current
from patches. That, rather than the absent socket, is why a mirror wants to run
in-process.
The mapping between your documents and your tables stays application-specific. datadata supplies the client and the callback, not the bridge.
Tests and demos
Section titled “Tests and demos”The in-process bus is also why datadata is easy to exercise: the test suite runs real client/server pairs with no infrastructure, and the live demos run the same way — a complete sync engine, client and server, inside your browser tab. In Contingency, the game’s simulation is an in-process client of its own: it moves the enemies, pays out gold, and writes the waves and lives.