Build a live board for permit case 29. Reviewer 47 belongs to organization 6; reviewer 62 cannot view that case. The browser opens one secure socket, subscribes to the case after the server checks current permission, and receives committed case versions. If the connection drops, it reauthenticates and asks for replay; an expired cursor triggers a fresh authorized snapshot. A mobile reviewer may fall behind a burst, so the server caps queued bytes and lets that client recover durable state rather than buffering indefinitely. Presence indicates recent activity and expires when a sleeping device stops sending evidence. A rolling deployment must drain old connections without losing committed events.
Project: live permit case board
Build contract
- Validate browser origin and session at upgrade, then authorize every private subscribe or mutation message against the current case.
- Persist versioned case changes before fanout; deduplicate events, reconcile gaps, and deny replay after permission revocation.
- Cap queue bytes and message size, expire presence leases, and reconnect with jitter after a bounded server drain.
Implementation checkpoint
function nextCaseStep(currentVersion, eventVersion) {
if (eventVersion <= currentVersion) return "ignore-old";
return eventVersion === currentVersion + 1 ? "apply" : "load-snapshot";
}
console.log(nextCaseStep(47, 49));
// Output: load-snapshotCost and boundaries
For S subscribers, publishing one event requires O(S) delivery attempts unless a broker changes the distribution path. Memory must remain bounded per connection; a 63-kilobyte queue cap across 900 sockets is already a material budget. Durable replay storage grows with retained events, while presence heartbeats add traffic proportional to connection count and interval. Measure publish-to-display latency, queue bytes, replay depth, gap frequency, revoked-event delay, false-presence duration, and reconnection surge during deployment. Keep full private messages and session material out of broad logs. A socket result is a delivery attempt; the committed case record remains the source of truth.
Failure drill
Try an unauthorized browser origin with a valid cookie, then a valid connection that subscribes to a foreign-tenant case. Revoke reviewer 47 while a connection stays open and publish a private event. Deliver version 49 before 48, duplicate version 50, and expire the replay cursor; the final board must match an authorized snapshot. Throttle one recipient during a burst of 63 updates per second and confirm its queue stays bounded while fast recipients continue. Sleep a laptop without a close frame and watch presence expire. Drain a node with 900 active clients; clients reconnect with jitter, current permission, and no missing durable changes.
Acceptance checks
- Unauthorized origins, sessions, and channel requests receive no private events.
- Reordered, duplicate, missing, and expired-history events converge on current case state.
- One slow consumer cannot grow memory without bound or block fast consumers.
- Presence expiry and rolling drain do not become edit locks or erase committed changes.
Common Mistakes
- Checking permission only when the socket opens.
- Treating arrival order as the case version order.
- Keeping an unlimited queue for slow connections.
Related lessons
Realtime Connection and Event Delivery; WebSocket Handshake, Session, and Channel Authorization; Event Sequence, Replay, and Gap Reconciliation; Socket Fanout, Backpressure, and Slow Consumers; Presence Expiry, Heartbeats, and Connection Drain.
