Topic Overview
WebSockets: Concepts, Internals & Interview Use Cases
Learn WebSocket protocol for full-duplex, persistent communication between client and server. Understand handshake, frame format, and use cases.
WebSockets
Why This Matters
Think of WebSockets like a phone call versus sending letters. HTTP is like sending lettersโyou write a letter (request), send it, wait for a reply (response), then the connection closes. WebSockets is like a phone callโyou dial once, the connection stays open, and you can talk back and forth in real time.
This matters because many applications need real-time communication. Chat apps, live notifications, collaborative editing, gamingโthese all need the server to push data to the client immediately. With HTTP, the client would have to keep asking "any updates?" (polling), which wastes resources and adds latency. WebSockets lets the server push data instantly.
In interviews, when someone asks "How would you design a real-time chat system?", they're testing whether you understand WebSockets. Do you know when to use WebSockets vs HTTP? Do you understand the handshake process? Most engineers don't. They just use HTTP polling and wonder why their app feels slow.
What Engineers Usually Get Wrong
Most engineers think "WebSockets are always better than HTTP." But WebSockets have overheadโthey keep connections open, which consumes server resources. For simple request-response patterns, HTTP is simpler and more efficient. WebSockets make sense when you need bidirectional, real-time communication.
Engineers also forget to handle reconnection. WebSocket connections can drop (network issues, server restarts). If your client doesn't reconnect, users lose functionality. Always implement automatic reconnection with exponential backoff.
How This Breaks Systems in the Real World
A chat application was using HTTP pollingโthe client asked for new messages every 2 seconds. Under normal load, this worked. But during peak hours, the server was handling 10,000 clients, each polling every 2 seconds = 5,000 requests per second. The server couldn't handle the load. Response times spiked. The service became unusable.
The fix? Use WebSockets. Each client maintains one persistent connection. The server pushes messages immediately when they arrive. This reduced server load from 5,000 requests/second to just the actual messages (maybe 100/second). But the real lesson is: polling doesn't scale. Use WebSockets for real-time communication.
Another story: A service was using WebSockets but didn't implement reconnection. When the server restarted (deployment), all WebSocket connections dropped. The client didn't reconnect automatically. Users had to refresh the page to reconnect. This created a poor user experience. The fix? Implement automatic reconnection with exponential backoff. Detect connection drops and reconnect automatically.
What are WebSockets?
WebSocket provides:
- Full-duplex communication: Both client and server can send data simultaneously
- Persistent connection: Connection stays open (unlike HTTP)
- Low overhead: Minimal protocol overhead after handshake
- Real-time: Instant bidirectional communication
Use cases:
- Real-time chat applications
- Live notifications
- Collaborative editing
- Gaming
- Financial tickers
- Live sports scores
WebSocket vs HTTP
HTTP (Request-Response)
Client โ Server: GET /api/data
Server โ Client: Response (connection closes)
For updates: Client must poll repeatedly
Client โ Server: GET /api/data (poll 1)
Client โ Server: GET /api/data (poll 2)
Client โ Server: GET /api/data (poll 3)
Problems:
- Polling overhead: Repeated requests
- Latency: Delay between polls
- Server load: Many unnecessary requests
WebSocket (Persistent Connection)
Client โ Server: Persistent connection
Client โ Server: Message 1
Server โ Client: Message 2
Client โ Server: Message 3
Server โ Client: Message 4
(Connection stays open)
Benefits:
- No polling: Server can push data immediately
- Low latency: Instant communication
- Efficient: Single connection, minimal overhead
WebSocket Handshake
WebSocket starts as HTTP request, then upgrades to WebSocket protocol.
Client Request
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://example.com
Key headers:
- Upgrade: websocket
- Connection: Upgrade
- Sec-WebSocket-Key: Random base64-encoded key
- Sec-WebSocket-Version: Protocol version (13)
Server Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Key points:
- Status 101: Switching Protocols
- Sec-WebSocket-Accept: Computed from client key + magic string
Key Calculation
1import crypto from 'crypto';23function computeAcceptKey(clientKey: string): string {4 // Compute Sec-WebSocket-Accept from client key5 const magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";6 const combined = clientKey + magicString;7 const sha1Hash = crypto.createHash('sha1').update(combined).digest();8 return sha1Hash.toString('base64');9}1011// Example12const clientKey = "dGhlIHNhbXBsZSBub25jZQ==";13const acceptKey clientKey
WebSocket Frame Format
After handshake, data sent in frames:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
Fields:
- FIN: Final fragment (1) or more fragments (0)
- RSV: Reserved bits
- Opcode: Frame type (text, binary, close, ping, pong)
- MASK: Masking key present (client must mask, server must not)
- Payload length: Length of payload data
- Masking key: 32-bit key (if MASK=1)
- Payload data: Actual data
Examples
WebSocket Server
1import WebSocket from 'ws';23const wss = new WebSocket.Server({ port: 8080 });45wss.on('connection', (ws: WebSocket, req: any) => {6 console.log('Client connected');78 // Send welcome message9 ws.send('Welcome to WebSocket server!');1011 // Handle messages12 ws.on('message', (message: Buffer) => {
WebSocket Client
1// Create WebSocket connection2const ws = new WebSocket('ws://localhost:8080');34// Connection opened5ws.onopen = () => {6 console.log('Connected to server');7 ws.send('Hello Server!');8};910// Receive message11ws.onmessage = (event: MessageEvent) => {12 console.log('Received:', event.data);13};
WebSocket with Authentication
1import WebSocket from 'ws';2import jwt from 'jsonwebtoken';34const wss = new WebSocket.Server({5 port: 8080,6 verifyClient: (info: any) => {7 // Verify token from query string or headers8 const token = new URL(info.req.url, 'http://localhost').searchParams.get('token');910 try {11 jwt.verify(token!, 'secret')
WebSocket Reconnection
1class WebSocketClient {2 private url: string;3 private ws: WebSocket | null = null;4 private reconnectInterval: number = 1000;5 private maxReconnectInterval: number = 30000;6 private reconnectDecay: number = 1.5;7 private shouldReconnect: boolean = true;89 constructor(url: string) {10 this.url = url;11 }1213 connect() {14 ws url
Common Pitfalls
- Not handling reconnection: Connection drops, client doesn't reconnect. Fix: Implement automatic reconnection with exponential backoff
- No heartbeat/ping: Don't know if connection is alive. Fix: Send ping frames periodically, close if no pong
- Not handling backpressure: Sending too fast, overwhelming server. Fix: Check
bufferedAmount, throttle sending - Security issues: Not validating origin, no authentication. Fix: Validate origin, implement authentication
- Memory leaks: Not cleaning up event listeners. Fix: Remove listeners on close, limit connection lifetime
- Not handling frame fragmentation: Large messages split into multiple frames. Fix: Handle FIN bit, reassemble fragments
Interview Questions
Beginner
Q: What are WebSockets and why are they used instead of HTTP?
A:
WebSockets provide full-duplex, persistent connections between client and server.
Why used instead of HTTP:
- Real-time communication: Server can push data immediately (no polling)
- Lower latency: No HTTP overhead after handshake
- Efficient: Single persistent connection vs multiple HTTP requests
- Bidirectional: Both client and server can send data simultaneously
HTTP vs WebSocket:
HTTP (Request-Response):
Client โ Server: GET /api/data
Server โ Client: Response (connection closes)
For updates: Must poll repeatedly
WebSocket (Persistent):
Client โ Server: Persistent connection
Server โ Client: Push data immediately
No polling needed
Use cases:
- Real-time chat
- Live notifications
- Collaborative editing
- Gaming
- Financial tickers
Intermediate
Q: Explain the WebSocket handshake process and frame format.
A:
Handshake Process:
-
Client Request (HTTP Upgrade)
GET /chat HTTP/1.1 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 -
Server Response (101 Switching Protocols)
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= -
Key Calculation
1import crypto from 'crypto';23const acceptKey = crypto4 .createHash('sha1')5 .update(clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")6 .digest('base64');
Frame Format:
[FIN|RSV|Opcode|MASK|Payload Length|Masking Key|Payload Data]
Fields:
- FIN: Final fragment (1) or more fragments (0)
- Opcode: Frame type (0x1=text, 0x2=binary, 0x8=close, 0x9=ping, 0xA=pong)
- MASK: Masking key present (client must mask, server must not)
- Payload length: Length of data (7, 16, or 64 bits)
- Masking key: 32-bit key (if MASK=1, client frames)
- Payload data: Actual message data
After handshake:
- Connection upgraded to WebSocket protocol
- Data sent in frames (not HTTP)
- Connection stays open until closed
Senior
Q: Design a scalable WebSocket system that handles millions of concurrent connections. How do you handle load balancing, message routing, and connection management?
A:
1class ScalableWebSocketSystem {2 private servers: WebSocketServer[];3 private loadBalancer: LoadBalancer;4 private messageRouter: MessageRouter;5 private connectionManager: ConnectionManager;6 private pubsub: PubSub;78 constructor() {9 // Multiple WebSocket servers10 this.servers = [11 new WebSocketServer({ port: 8080 }),12 new WebSocketServer({ port: 8081 }),13 new WebSocketServer({ port:
Features:
- Load balancing: Distribute connections across servers
- Message routing: Route messages to correct server
- Pub/Sub: Cross-server communication via Redis
- Connection management: Track connections, handle disconnections
- Heartbeat: Keep connections alive, detect dead connections
- Rate limiting: Prevent abuse
- Scaling: Horizontal scaling with multiple servers
Failure Stories You'll Recognize
The Polling Storm: A chat application was using HTTP pollingโthe client asked for new messages every 2 seconds. Under normal load, this worked. But during peak hours, the server was handling 10,000 clients, each polling every 2 seconds = 5,000 requests per second. The server couldn't handle the load. Response times spiked. The service became unusable. The fix? Use WebSockets. Each client maintains one persistent connection. The server pushes messages immediately when they arrive. This reduced server load from 5,000 requests/second to just the actual messages.
The Connection Drop: A service was using WebSockets but didn't implement reconnection. When the server restarted (deployment), all WebSocket connections dropped. The client didn't reconnect automatically. Users had to refresh the page to reconnect. This created a poor user experience. The fix? Implement automatic reconnection with exponential backoff. Detect connection drops and reconnect automatically.
The Memory Leak: A service was using WebSockets for real-time notifications. Each connection stored event listeners. When connections closed, the listeners weren't removed. Over time, memory usage grew. After a week, the service ran out of memory and crashed. The fix? Always remove event listeners when connections close. Use weak references or connection pools.
What Interviewers Are Really Testing
They want to hear you talk about when to use WebSockets vs HTTP, connection management, and scaling strategies. Junior engineers say "use WebSockets for real-time." Senior engineers say "WebSockets for bidirectional real-time communication, HTTP for request-response. Always implement reconnection, heartbeat, and rate limiting. For scaling, use load balancing and pub/sub for cross-server communication."
When they ask "How would you design a real-time system?", they're testing:
-
Do you understand when WebSockets make sense vs HTTP?
-
Do you know how to handle connection drops and reconnection?
-
Can you design a scalable WebSocket system?
-
HTTP/1 vs HTTP/2 vs HTTP/3 - WebSockets start as HTTP connections then upgrade, understanding HTTP explains WebSocket handshake
-
TCP vs UDP - WebSockets use TCP for reliable bidirectional communication, understanding TCP explains WebSocket behavior
-
Three-Way Handshake (TCP) - WebSocket connections require TCP handshake, understanding TCP handshakes explains WebSocket connection establishment
-
Keep-Alive vs Long Polling - WebSockets are an alternative to long polling, understanding polling helps appreciate WebSocket benefits
-
Connection Pooling - WebSocket connections are persistent, understanding connection management helps optimize WebSocket usage
-
WebSocket: Full-duplex, persistent connection for real-time communication
-
Handshake: Starts as HTTP, upgrades to WebSocket (101 Switching Protocols)
-
Frame format: Binary frames with opcode, mask, payload length, data
-
Benefits: No polling, low latency, efficient, bidirectional
-
Use cases: Real-time chat, notifications, gaming, collaborative editing
-
Connection management: Handle reconnection, heartbeat, backpressure
-
Scaling: Load balancing, message routing, pub/sub for cross-server communication
-
Best practices: Implement reconnection, heartbeat, rate limiting, authentication
How InterviewCrafted Will Teach This
We'll teach this through production failures, not protocol specifications. Instead of memorizing "WebSocket uses a handshake," you'll learn through scenarios like "what happens when 10,000 clients poll every 2 seconds?"
You'll see how WebSockets affect performance, scalability, and user experience. When an interviewer asks "how would you design a real-time system?", you'll think about connection management, reconnection strategies, and scalingโnot just "use WebSockets."
Key Takeaways
WebSocket: Full-duplex, persistent connection for real-time communication
Handshake: Starts as HTTP, upgrades to WebSocket (101 Switching Protocols)
Frame format: Binary frames with opcode, mask, payload length, data
Benefits: No polling, low latency, efficient, bidirectional
Use cases: Real-time chat, notifications, gaming, collaborative editing
Connection management: Handle reconnection, heartbeat, backpressure
Scaling: Load balancing, message routing, pub/sub for cross-server communication
Best practices: Implement reconnection, heartbeat, rate limiting, authentication
Related Topics
HTTP/1 vs HTTP/2 vs HTTP/3
WebSockets start as HTTP connections then upgrade, understanding HTTP explains WebSocket handshake
TCP vs UDP
WebSockets use TCP for reliable bidirectional communication, understanding TCP explains WebSocket behavior
Three-Way Handshake (TCP)
WebSocket connections require TCP handshake, understanding TCP handshakes explains WebSocket connection establishment
Keep-Alive vs Long Polling
WebSockets are an alternative to long polling, understanding polling helps appreciate WebSocket benefits
Connection Pooling
WebSocket connections are persistent, understanding connection management helps optimize WebSocket usage