Hibernation
Why connection state cannot live in memory.
A Durable Object is torn down and rebuilt whenever it hibernates. Any connection state held in process memory is gone.
This is not a rare edge case. Hibernation is the normal lifecycle of an idle
Durable Object, so a WebSocket handler that keeps its state in a Map will
silently stop answering after the first quiet period.
Where state lives
Identity, client ID, and subscription records live in the tenant's own SQLite. A hibernatable WebSocket carries nothing but its connection ID in its attachment, which keeps the payload far below the attachment size limit however large an identity becomes.
const connectionId = connections.openConnection(verifiedIdentity);
attachConnectionId(server, connectionId);Because there is no in-memory map at all, hibernation safety is structural rather than something to remember.
Waking up
On every instantiation the object rebuilds its subscriptions from storage
before any event is delivered, inside blockConcurrencyWhile. A restored
subscription recomputes from storage and keeps its persisted sequence, so the
next patch still lands exactly one past what the client already holds — the
reconnect is seamless and needs no snapshot.
Waking is also where the rows of any connection without a live socket are released: a socket that vanished during teardown never delivers a close event, so this is the only place that state can be reclaimed. A socket whose connection row is missing is closed rather than served, because it can no longer be authorized.
Cost
Rebuilding is not free — roughly 16 ms of compute for 500 subscriptions, paid
inside blockConcurrencyWhile before the object serves its first event.
Keep per-tenant subscription counts in the hundreds. → Limits