SyncInbox Durable Object
src/durable-objects/sync-inbox.ts defines SyncInbox, the project’s first and only Durable Object (ADR-011). Each authenticated user connects to one inbox keyed by their verified userId; the inbox fans a tiny SyncSignal (“surface X changed”) to that user’s open sockets.
Connection handling
Section titled “Connection handling”fetch(request)accepts the WebSocket upgrade and callsthis.ctx.acceptWebSocket(server)— hibernatable WebSockets (notserver.accept()), so idle inboxes pause duration billing (constitution §8.4). Idle cost ≈ 0 is the economic point of the design.- Connection cap — at most
MAX_CONNSopen sockets per user; on a new connection beyond the cap the oldest sockets are evicted withCLOSE_CODES.CONNECTION_CAP(multi-tab soft cap). notify(signal)— the RPC the Worker calls to broadcast aSyncSignalto all open sockets.webSocketClose/webSocketError— lifecycle hooks that clean up connection state.
Boundaries
Section titled “Boundaries”- The DO holds ephemeral connection state only — no business data; D1 remains the single source of truth (constitution §7.10).
- It is unreachable except through the authenticated
/api/v1/sync/streamupgrade route, which runs Clerk auth and an Origin/CSWSH check before forwarding to the user’s stub (constitution §7.12). - The
SyncSignalshape andMAX_CONNS/CLOSE_CODESconstants are shared viasrc/lib/sync/signal.ts.
Related: Worker API & Clerk Auth (the upgrade route + auth), LiveConnection WS Client (the browser end), DB Schema & Notify-Affected (who gets notified).