Real-Time UI with WebSockets
Pathrule3 Rules • 2 Memories • 1 Skill
A WebSocket provides an ordered byte stream for one live connection, not durable delivery across disconnects, browser sleep, server restarts, deployment, or a client that processes messages slower than the producer sends them. This pattern constrains authenticated connection setup, message validation, and bounded queues; it records sequence, resume, presence, and optimistic-state decisions and provides a reconnect failure test. It complements Kafka and background-job patterns by focusing on the browser-facing session, where ephemeral connection state must reconcile with an authoritative API or event log.
Suggested path map
Pathrule places each piece on the matching path, so your assistant only sees it where it belongs. This is the scoping you get on import; you can adjust it in your workspace.
Rules
3Validate every message against a versioned envelope/server/realtimehighstrictUse bounded payload schemas, message type allowlists, correlation identity, and explicit protocol errors on both client and server.
| 1 | WebSocket frames are untrusted input without HTTP route and body-parser boundaries. A generic event name plus arbitrary object recreates remote procedure calls without a reviewable contract. |
| 2 | |
| 3 | - Define an envelope with protocol version, type, message or operation identity, and a payload schema per allowed message. |
| 4 | - Reject unknown types, oversized frames, invalid nesting, and unsupported versions before dispatching to domain behavior. |
| 5 | - Separate commands, events, acknowledgements, and errors so clients do not confuse a requested action with an authoritative state transition. |
| 6 | - Log protocol type, stable identity, size, and outcome without recording secret or personal payload fields. |
| 7 | |
| 8 | See /tests/realtime for the adjacent decision or procedure that completes this constraint. |
Bound outbound and inbound connection buffers/server/realtimehighstrictSet queue, frame, rate, and processing limits, then close or degrade slow consumers with a recoverable reason.
| 1 | A connection that receives faster than it can transmit or process accumulates memory. Backpressure must become a protocol decision before one slow browser harms every session in the process. |
| 2 | |
| 3 | - Track buffered bytes and queued messages per connection and define a maximum with a close, snapshot, or coalescing policy. |
| 4 | - Coalesce replaceable state updates such as progress or presence instead of retaining every intermediate value. |
| 5 | - Keep durable domain events outside the socket process so dropping an ephemeral connection does not lose the authoritative transition. |
| 6 | - Apply inbound rate and concurrency limits before expensive validation or database work, and return a protocol-level throttle or close reason clients understand. |
| 7 | |
| 8 | See /src/realtime for the adjacent decision or procedure that completes this constraint. |
Memories
2Presence is leased, approximate state/src/realtimeRepresent presence with heartbeats and expiry, and never use it as durable identity, authorization, or business truth.
| 1 | Disconnect events are not guaranteed when a laptop sleeps, a network changes, or a process dies. Presence must expire without a clean close and tolerate brief disagreement between viewers. |
| 2 | |
| 3 | - Issue a connection or session presence identity distinct from the user account and refresh it through bounded heartbeats. |
| 4 | - Expire presence after a documented lease and communicate that online indicators are approximate rather than instantaneous truth. |
| 5 | - Aggregate multiple tabs and devices intentionally so one closing tab does not mark a still-connected user offline. |
| 6 | - Keep authorization and durable workflow state in the authoritative backend; presence can inform UI but cannot grant access or prove attendance. |
| 7 | |
| 8 | See /server/realtime for the rule or workflow that puts this decision into practice. |
Skills
1test-websocket-resynchronization/rootBreak and resume live connections across gaps, duplicates, reordering, slow consumers, token changes, and server restarts.
| 1 | --- |
| 2 | name: test-websocket-resynchronization |
| 3 | description: Test a WebSocket protocol or real-time UI change before release. |
| 4 | --- |
| 5 | |
| 6 | # Test Websocket Resynchronization |
| 7 | |
| 8 | Run this procedure when the affected surface changes, before the result is promoted to production. Record evidence for every step instead of accepting a plausible-looking result. |
| 9 | |
| 10 | - [ ] Connect with valid, expired, unauthorized, wrong-origin, malformed, oversized, and unsupported-version inputs and confirm rejection occurs before subscription or domain work. |
| 11 | - [ ] Produce events while the client is disconnected, then reconnect from a current, old, invalid, and missing cursor; verify replay or snapshot behavior. |
| 12 | - [ ] Duplicate and reorder events around optimistic UI changes and prove the final state follows authoritative sequence without duplicate rows or effects. |
| 13 | - [ ] Throttle the client and server consumer to grow buffers; verify coalescing, limits, close reason, and recovery without process-level memory growth. |
| 14 | - [ ] Restart and deploy socket servers while several tabs and devices are connected, then revoke access and confirm every connection eventually loses the subscription. |
| 15 | |
| 16 | ## Exit criteria |
| 17 | |
| 18 | The change is complete only when the expected behavior, failure behavior, and rollback path have all been exercised with representative data. Preserve the evidence with the change so the next operator can repeat the same checks. |
Why this pattern
AI agents often authenticate only the initial page, assume reconnect preserves missed events, append duplicates without sequence identity, or allow an unbounded client message queue.
Built for Frontend and backend teams building collaborative, presence, notification, monitoring, or live-update interfaces.
Keeps your assistant from:
- Applying the same event twice after reconnect
- Missing events produced while the browser was suspended
- Treating a socket connection as permanent authorization
- Crashing a client or server through unbounded buffered messages
- License
- Apache-2.0
- Version
- 1.0.0
- Updated
- 2026-08-25