WebSocket is a communication protocol that provides full-duplex, bidirectional communication between a client and server over a single, long-lived TCP connection. Unlike HTTP where the client always initiates requests, WebSocket allows the server to push data to clients at any time.
WebSocket
A protocol enabling full-duplex, real-time communication between client and server.
HTTP vs WebSocket
| Aspect | HTTP | WebSocket |
|---|---|---|
| Connection | New connection per request | Single persistent connection |
| Direction | Client → Server only | Bidirectional |
| Overhead | Headers sent every request | Minimal after handshake |
| Real-time | Polling required | Native push capability |
| Use case | Request/response APIs | Real-time updates |
How WebSocket Works
1. Handshake:
Client sends HTTP request with Upgrade: websocket header. Server responds with 101 (Switching Protocols). Connection upgrades from HTTP to WebSocket.
2. Data transfer: Both sides can send messages at any time. Messages are framed with minimal overhead (just a few bytes vs HTTP's hundreds).
3. Connection stays open: No need to reconnect for each message. The connection persists until either side closes it.
4. Heartbeats: Ping/pong frames keep connection alive and detect dead connections. If no pong received, connection is considered dead.
When to Use WebSocket
Real-time notifications: Chat messages, alerts, live updates. Server pushes new data instantly without client asking.
Live collaboration: Google Docs-style editing, Figma multiplayer, shared whiteboards. Changes sync immediately across users.
Live data feeds: Stock prices, sports scores, cryptocurrency tickers. Data changes frequently and must be fresh.
Gaming: Multiplayer games need instant communication. HTTP latency would make games unplayable.
IoT and telemetry: Sensors sending frequent readings. Opening a new HTTP connection for each reading is wasteful.
When NOT to Use WebSocket
Simple CRUD APIs: If your app just fetches and updates data occasionally, REST is simpler.
Infrequent updates: If data changes every few minutes, polling or SSE might be simpler than maintaining WebSocket connections.
One-way server push: If you only need server-to-client updates (no client messages), Server-Sent Events (SSE) is simpler.
Behind restrictive proxies: Some corporate proxies block WebSocket. Have an HTTP fallback ready.
WebSocket API Basics
Connection lifecycle:
onopen: Connection establishedonmessage: Message receivedonerror: Error occurredonclose: Connection closed
Sending messages:
send(data): Send string or binary dataclose(): Gracefully close connection
Ready states:
CONNECTING (0): Handshake in progressOPEN (1): Ready to communicateCLOSING (2): Closing handshakeCLOSED (3): Connection closed
Connection Management
Reconnection: Networks fail. Connections drop. Always implement automatic reconnection with exponential backoff:
- First retry: 1 second
- Second retry: 2 seconds
- Third retry: 4 seconds
- Max: 30 seconds
Heartbeats: Send periodic pings to detect dead connections. If the server doesn't respond, reconnect.
Graceful shutdown: Close connections properly when user navigates away. Send close frame, don't just abandon.
Common Patterns
Message types:
Use a type field to distinguish messages:
{type: "chat", payload: {text: "Hello"}}
{type: "presence", payload: {user: "john", status: "online"}}
Request/response over WebSocket:
Add request IDs to correlate responses:
{id: "abc123", type: "getUser", payload: {userId: 1}}
{id: "abc123", type: "userResponse", payload: {name: "John"}}
Rooms/channels:
Subscribe to specific topics:
{type: "subscribe", channel: "chat:general"}
Best Practices
Structure your messages: Use JSON with clear types. Don't send unstructured text.
Handle disconnection: Users don't notice when connections drop. Show connection status, queue messages, reconnect automatically.
Implement backpressure: If client is slow, buffer messages. If buffer is full, drop oldest or close connection.
Authenticate properly: Send auth token in first message or query param. Don't rely on cookies alone.
Monitor connections: Track open connections, message rates, errors. WebSocket issues are hard to debug without metrics.
Common Mistakes
1. No reconnection logic: Connection drops, app breaks, user refreshes. Always auto-reconnect.
2. Massive payloads: WebSocket isn't for file transfers. Send references (URLs) for large data.
3. Ignoring close codes:
1000 = normal close, 1006 = abnormal close, 1001 = going away. Different codes need different handling.
4. Not handling slow clients: Fast server, slow client = memory leak. Implement backpressure or drop slow clients.
Code Examples
WebSocket Client with Reconnection
class WebSocketClient {
constructor(url) {
this.url = url;
this.reconnectDelay = 1000;
this.maxReconnectDelay = 30000;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('Connected');
this.reconnectDelay = 1000; // Reset delay on success
// Authenticate
this.send({ type: 'auth', token: getAuthToken() });
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};
this.ws.onclose = (event) => {
console.log(`Disconnected: ${event.code}`);
if (event.code !== 1000) {
this.scheduleReconnect();
}
};
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
}
scheduleReconnect() {
setTimeout(() => {
console.log(`Reconnecting in ${this.reconnectDelay}ms...`);
this.connect();
// Exponential backoff
this.reconnectDelay = Math.min(
this.reconnectDelay * 2,
this.maxReconnectDelay
);
}, this.reconnectDelay);
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
handleMessage(message) {
switch (message.type) {
case 'chat':
displayChatMessage(message.payload);
break;
case 'notification':
showNotification(message.payload);
break;
}
}
}Related Terms
JWT (JSON Web Token)
A compact, URL-safe token format for securely transmitting information between parties.
REST API
An architectural style for building web APIs using HTTP methods and stateless communication.
Latency
The time delay between a request being sent and a response being received.
Query Parameters
Key-value pairs appended to URLs for filtering, sorting, and customizing API requests.