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
API Testing
The process of verifying that APIs work correctly, securely, and perform well.
REST API
An architectural style for building web APIs using HTTP methods and stateless communication.
HTTP Status Codes
Standard response codes that indicate the result of an HTTP request.
OpenAPI Specification
A standard format for describing REST APIs, enabling documentation and code generation.