Reading WebSocket close codes like a protocol native
The close code is the first diagnostic fact of any dropped connection — and most dashboards never show it. The ones that matter:
| Code | Meaning | Usual culprit |
|---|---|---|
| 1000 | Normal closure | Clean shutdown — not an error |
| 1001 | Going away | Server restart or deploy |
| 1006 | Abnormal closure | Network/proxy/TLS failure, no handshake |
| 1008 | Policy violation | Auth rejected, origin not allowed |
| 1009 | Message too big | Frame exceeded server’s limit |
| 1011 | Server error | Unhandled exception server-side |
A reconnecting client should treat 1000/1001 as expected, back off exponentially on 1006, and stop retrying on 1008 — hammering an endpoint that rejected your credentials just gets your IP rate-limited.
WebSocket or SSE? Choose by direction
Both deliver real-time updates; the decision is traffic direction. Server-Sent Events are one-way (server → client), ride on plain HTTP, reconnect automatically, and pass through proxies and CDNs effortlessly — the right choice for feeds, notifications, progress bars, and LLM token streams. WebSockets are bidirectional with lower per-message overhead — necessary for chat, multiplayer state, and collaborative editing where the client talks back constantly. The honest heuristic: if you only need to receive, SSE is operationally simpler; teams reach for WebSockets by default and inherit connection-management complexity they didn’t need.
Testing authenticated endpoints
Browsers don’t let WebSocket clients set arbitrary headers, so real-world auth lands in one of three places: a token in the query string (wss://api.example.com/feed?token=... — simplest, but tokens leak into server logs), a ticket pattern (fetch a short-lived ticket over HTTPS, pass it in the URL — the production-grade answer), or the Sec-WebSocket-Protocol field abused as a token carrier. When a connection authenticates in your backend tests but fails from this tester, the server is usually reading auth from a cookie or header your test setup sent implicitly — re-test with the token explicitly in the URL to confirm which mechanism the endpoint really uses.