Why WebSockets
HTTP is request/response: the client asks, the server answers, the connection closes. For real-time features — chat, live dashboards, notifications, multiplayer — you want the *server* to push data the instant something happens. WebSockets keep a single connection open for low-latency, two-way messaging, and JSON is the natural payload format.
Design a message envelope
Raw strings get messy fast. Wrap every message in a consistent JSON envelope with a type and a payload:
{ "type": "chat.message", "payload": { "room": "general", "text": "hi" } }A shared envelope lets both sides switch on type and route messages cleanly:
socket.onmessage = (e) => {
const msg = JSON.parse(e.data);
switch (msg.type) {
case "chat.message": renderMessage(msg.payload); break;
case "presence.update": updatePresence(msg.payload); break;
case "error": showError(msg.payload); break;
}
};
function send(type, payload) {
socket.send(JSON.stringify({ type, payload }));
}Common message types
| Type | Direction | Purpose |
|---|---|---|
*.subscribe | client → server | Join a room/channel |
*.message | both | Actual data |
presence.update | server → client | Who is online |
ack | server → client | Confirm receipt of a client action |
error | server → client | Something went wrong |
ping/pong | both | Keep-alive heartbeat |
Handle the hard parts
- Heartbeats. Send periodic
ping/pongso dead connections are detected and cleaned up. - Reconnection. Networks drop. Implement client reconnect with exponential backoff, and re-subscribe to channels on reconnect.
- Message ordering and dedupe. Include a sequence number or id if order matters or messages might be re-delivered.
- Backpressure. If a client is slow, do not buffer unbounded messages — drop or coalesce (especially for high-frequency dashboard updates).
Authentication
WebSocket upgrade requests can carry auth, but a common pattern is to authenticate on connect (token in the query or first message) and then validate every privileged action server-side. Never trust the client's claimed identity in subsequent messages without verification.
When not to use WebSockets
If you only need server→client updates (live scores, notifications) and not true bidirectional chat, Server-Sent Events (SSE) are simpler: they run over plain HTTP, auto-reconnect, and stream JSON deltas. Reach for WebSockets when you need low-latency messages in *both* directions.