Practice this topic in a realistic system design interview
HTTP is a request-response protocol: the client asks, the server responds, and the application moves on. That model gets awkward when the server needs to send data the moment something happens, such as a new chat message, a price update, or a teammate moving their cursor.
Polling wastes requests and adds delay. Long polling improves things, but each response still ends the request and forces the client to connect again.
WebSockets keep one connection open so both the client and server can send messages whenever they need to. The connection stays open, works in both directions, and sends complete messages.
This chapter explains how the WebSocket handshake works, how WebSockets compare with HTTP, polling, long polling, and SSE, where WebSockets fit well, where they do not, what changes when you run many open connections, and how to build a basic WebSocket server and client.
A WebSocket connection starts as HTTP, then upgrades to the WebSocket protocol. After the upgrade, the client and server can both send messages over the same TCP connection.
The connection works in both directions, stays open across many messages, and avoids sending full HTTP headers with every message. Because WebSockets run over TCP, messages are delivered in order and retransmitted if needed. Applications send text or binary messages rather than raw byte streams.
This makes WebSockets a good fit for real-time application data. It does not make them the answer to every real-time problem. For audio or video calls, WebRTC is usually a better fit. For one-way server updates, Server-Sent Events may be simpler.
Loading simulation...
The browser opens a WebSocket with a URL such as:
ws:// is unencrypted. wss:// is WebSocket over TLS, similar to HTTPS. Production applications should use wss://.
The browser sends an HTTP request asking the server to switch protocols:
If the server accepts the upgrade, it returns 101 Switching Protocols:
At that point, the HTTP part is done. The WebSocket protocol now uses the same connection.
Most WebSocket deployments use the HTTP/1.1 upgrade flow. WebSockets can also work with newer HTTP versions in some environments, but support across clients, proxies, and load balancers is not always consistent. For system design interviews and most production discussions, start with the HTTP/1.1 upgrade model.
WebSocket data is carried in frames. A frame is a small protocol unit used to move data over the connection. One application message may fit in one frame or be split across several frames. The protocol supports text frames, binary frames, close frames, and ping/pong frames.
Browsers handle frames for you. Your application usually receives complete messages through an onmessage handler.
Because WebSockets run over TCP, delivery is ordered. That is helpful for chat and collaboration events, but it can hurt highly time-sensitive streams. If one packet is delayed, later messages wait behind it. This is one reason WebSockets are not ideal for real-time audio or video.
The right real-time option depends on message direction, latency needs, browser support, and operating cost.
| Technique | Direction | Best For | Trade-Off |
|---|---|---|---|
| Short polling | Client asks repeatedly | Simple status checks | Wastes requests and adds delay |
| Long polling | Server holds one request | Basic server push where WebSockets are unavailable | Reconnects after each response |
| Server-Sent Events | Server to client | Notifications, feeds, progress updates | One-way from server to browser |
| WebSockets | Client and server | Chat, collaboration, multiplayer state, live dashboards | Must manage many open connections |
| WebRTC | Peer/media transport | Audio, video, screen sharing, peer data | More complex NAT and media stack |
Use WebSockets when both sides need to send events whenever they happen. If only the server needs to push updates, SSE can be simpler. If clients only need occasional updates, normal HTTP or polling may be enough.
WebSockets work well when the product needs fast application messages in both directions.
Common examples:
WebSockets are less suitable for some workloads. Large file uploads or downloads are simpler over HTTP, and video streaming is better served by HLS, DASH, or WebRTC.
Server-only notifications often do not need a two-way connection, so SSE may be enough. Workloads that must store messages before delivery need delivery confirmations and replay built on top, because WebSockets alone do not provide them.
The important point is that WebSockets provide a transport. They do not automatically give you durable storage, ordering across servers, replay, moderation, permissions, or exactly-once delivery.
Here is a small Node.js server using the ws library.
And a browser client:
This is enough to demonstrate the protocol, but not enough for production. A real system needs login checks, clear message formats, backpressure, heartbeats, reconnect behavior, and a way to route messages across many server instances.
Scaling WebSockets is different from scaling normal HTTP APIs because connections stay open.
With normal HTTP, a load balancer can send each request to any healthy server. With WebSockets, a client may stay connected to one server for minutes or hours. That server now holds the connection for that client.
A production deployment puts a load balancer in front of WebSocket servers, tunes idle timeouts so healthy connections are not dropped unexpectedly, and uses a message broker or pub/sub system to route events between servers.
It also keeps per-connection state small, tracks which server currently holds each user's connection, drains connections gracefully during deploys, and applies rate limits per user and per connection.
Sticky sessions can help keep a user on the same server, but they are not a full design. If user A is connected to server 1 and user B is connected to server 2, the system still needs a way to deliver A's message to B.
A WebSocket connection can fail at any time. Laptops sleep. Phones switch networks. Proxies close idle connections. Deploys restart servers.
Good clients treat disconnects as normal. They reconnect with backoff, add a little randomness so everyone does not reconnect at once, subscribe again to rooms or streams, and resume from the last event ID when the product needs replay. They avoid queueing unlimited messages while offline and show stale or disconnected state when it matters to the user.
Servers also need backpressure handling. Backpressure means the server is producing messages faster than a client can receive them. If the server keeps buffering those messages, one slow client can become a memory problem.
Practical safeguards include limiting message size and capping the outgoing queue per connection. Drop or merge stale updates such as cursor positions, and close connections that cannot keep up. Use delivery confirmations only when the product truly needs them.
Heartbeats are another important detail. Servers can use WebSocket ping/pong frames to detect dead connections. Browser JavaScript does not expose protocol-level ping directly, so browser apps often send their own heartbeat messages when they need to check whether the connection is still alive.
WebSockets need the same security care as HTTP APIs, plus a few details specific to long-lived connections.
Use wss:// in production so traffic is encrypted. Authenticate the user during the handshake or immediately after connection, and check permissions for every room, topic, or action. A connected socket should not mean "allowed to do everything."
Watch for these common issues:
Origin header and require proper login checks.For internal services, do not assume a WebSocket connection is trusted just because it came from inside the network. Keep login and permission checks explicit.
WebSocket problems often show up as missing updates or stale UI, not clean request failures. Monitor connection state directly.
Useful metrics include:
Also log enough context to debug routing problems: user ID, connection ID, server instance, subscribed topics, and close code. Be careful not to log sensitive message contents.
WebSockets give web applications a long-lived, two-way channel between client and server. They fit chat, collaboration, live dashboards, multiplayer state, trading interfaces, and other products where both sides send small messages quickly. The connection starts with an HTTP upgrade, and after 101 Switching Protocols it uses the WebSocket protocol.
Either side can then send messages without opening a new HTTP request. Because it runs over TCP, delivery is ordered and reliable, but a delayed packet can hold back later messages.
A WebSocket is a transport, not a full system. Login, permissions, message formats, durable storage, replay, and rate limits still have to be added where the product needs them. Scaling requires a design that understands long-lived connections, including load balancing, pub/sub routing, deploy draining, heartbeats, and backpressure.
Use WebSockets when two-way real-time messaging is the core requirement. Use simpler HTTP, SSE, or polling when a long-lived two-way connection is not needed.
10 quizzes