Real-Time Bidirectional Communication

The standard HTTP protocol is strictly unidirectional: the client requests, the server responds, and the connection closes.

If you are building a real-time chat application, a multiplayer browser game, or a live stock ticker, HTTP is terrible. In the past, developers used Long Polling (the browser repeatedly asks the server "Do you have new messages?" every 1 second). This creates massive HTTP header overhead and crushes server CPU.

WebSockets solve this by establishing a persistent, full-duplex communication channel over a single TCP connection.

The WebSocket Handshake

A WebSocket connection actually begins its life as a standard HTTP GET request. The client asks the server to "upgrade" the connection.

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

If the server supports WebSockets, it responds with an HTTP 101 Switching Protocols status code.

At this exact moment, the HTTP protocol is abandoned. The TCP connection stays open, but the data flowing over it switches to the lightweight WebSocket binary framing protocol.

Key Advantages of WebSockets

  1. Full-Duplex: The server can actively push data down to the client at any moment without waiting for the client to ask.
  2. Extremely Low Latency: Because the TCP connection remains open, there is no 3-way handshake overhead for subsequent messages.
  3. Tiny Overhead: HTTP headers are bulky (often 1KB+ per request). WebSocket frames only require 2 to 10 bytes of header overhead per message.

Frames and Messages

Once upgraded, data travels as WebSocket frames. A message can be split across several frames, and frames carry an opcode indicating text, binary, ping, pong, or close. The ping/pong frames are a keepalive mechanism: if one side stops answering pings, the other side can drop the connection and reconnect. This is why a WebSocket's health often depends on correctly responding to pings.

Alternatives: SSE and HTTP/2 Streaming

WebSockets are not the only real-time option: - Server-Sent Events (SSE): a one-way stream from server to client over a long-lived HTTP response. Simpler than WebSockets for feeds (notifications, live scores) and works over plain HTTP. - HTTP/2 server push / streaming: multiplexed streams can carry long-lived responses, though server push has been largely deprecated in browsers.

Choose WebSockets when you need true bidirectional interaction; choose SSE when the client only listens.

Scaling Challenges

While WebSockets are amazing for performance, they are notoriously difficult to scale horizontally. - With HTTP, a Load Balancer can freely distribute requests across 10 servers. - With WebSockets, the TCP connection is persistent. If you have a chat app, and Alice connects to Server 1, and Bob connects to Server 2, how do they talk to each other? - The Solution: A centralized Pub/Sub message broker (like Redis or Kafka). When Alice sends a message to Server 1, Server 1 publishes it to Redis. Server 2 is subscribed to Redis, receives the message, and pushes it down the WebSocket to Bob.

Connection Limits and Reconnection

Browsers historically limited concurrent WebSocket connections per origin (often ~200 on HTTP/1.1), and intermediaries may terminate idle connections after a timeout. Production clients therefore implement automatic reconnect with exponential backoff and a resubscribe step. Losing a WebSocket should never lose data—design a sequence number or message ID so the client can request anything it missed while disconnected.