AlgoInsight

System Design

What Are WebSockets and Why Are They Used?

WebSockets give you a single, persistent, two-way channel between client and server - the foundation of every real-time app from chat to multiplayer games. Here's how they work and why they exist.

By Admin2026-06-1813 min readwebsocketsreal-timenetworkingsystem-designprotocolscommunication

Open a chat app and watch a message from a friend appear instantly, with no refresh and no delay. Play an online game and see other players move in real time. Edit a document with a colleague and watch their cursor and edits show up as they type. All of these share a requirement that the ordinary web can't easily meet: the server and client need to send each other messages instantly, in both directions, over a connection that stays open. That's exactly what WebSockets provide.

WebSockets are the foundation of real-time interactive applications on the web. This guide explains what a WebSocket is, how it works (including the handshake that starts it), why it exists when we already had HTTP, and where it's the right tool - and where it isn't.

The problem WebSockets solve

Normal web communication uses HTTP, which is built on a request-response model: the client sends a request, the server responds, and the connection closes. This is fine for loading pages, but it has two limitations for real-time apps.

First, the server can't initiate. In request-response, the server only ever speaks when spoken to. It can't push new data to the client on its own - so when the server has an update (a new message arrived), it has no way to tell the client directly.

Second, every exchange is a new connection with overhead. Each HTTP request sets up a connection, carries a load of headers, and tears down - fine occasionally, wasteful if you're exchanging many small messages rapidly.

Older workarounds (polling and long polling) tried to simulate real-time over HTTP, but they're inefficient - constantly opening connections, sending headers, asking "anything new?" WebSockets were created to solve this properly: one persistent connection, kept open, over which both sides can send messages freely, at any time, with minimal overhead.

What a WebSocket is

A WebSocket is a persistent, bidirectional, full-duplex communication channel between a client and a server over a single connection. Let's unpack those terms, because each one matters:

Once a WebSocket connection is established, sending a message in either direction is fast and lightweight - no new connection, no heavy headers, just the message. This is what makes WebSockets ideal for rapid, real-time, two-way communication.

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: HTTP request with "Upgrade: websocket"
    S->>C: 101 Switching Protocols (handshake accepted)
    Note over C,S: Connection stays open - now full-duplex
    C->>S: message ("hello")
    S->>C: message ("hi back")
    S->>C: message (pushed anytime, unprompted)
    C->>S: message (sent anytime)
This sequence diagram shows a WebSocket connection. The client sends an HTTP request asking to upgrade to a WebSocket. The server responds with "101 Switching Protocols," accepting the handshake. From then on, the connection stays open and full-duplex: the client and server send messages back and forth freely, and crucially, the server can push messages to the client at any time without being asked.

How a WebSocket connection works: the handshake

A WebSocket connection starts life as an ordinary HTTP request, then upgrades. This clever design lets WebSockets work over the existing web infrastructure (the same ports, through the same proxies) rather than requiring something entirely new.

The sequence:

  1. The handshake. The client sends an HTTP request with a special header asking to "upgrade" the connection to a WebSocket (Upgrade: websocket). This is a normal HTTP request - that's why it works through existing web infrastructure.
  2. The switch. If the server supports WebSockets and accepts, it responds with a special status (101 Switching Protocols), agreeing to upgrade. At this point, the connection stops being HTTP request-response and becomes a persistent WebSocket channel.
  3. Open communication. The connection now stays open. Both sides send messages freely, in both directions, at any time, until either side closes the connection.

The key insight is that the connection transforms from a one-time HTTP request into a long-lived two-way channel. After the handshake, the rules change completely - it's no longer "ask and answer," it's "an open line both parties can use whenever they want."

Here's roughly what using a WebSocket looks like from the client side (in the browser):

// Open a WebSocket connection
const socket = new WebSocket("wss://example.com/chat");

// Called once the connection is open
socket.onopen = () => {
  socket.send("Hello, server!");   // client can send anytime
};

// Called whenever the SERVER pushes a message - unprompted
socket.onmessage = (event) => {
  console.log("Server says:", event.data);
};

// Called if the connection closes
socket.onclose = () => {
  console.log("Connection closed");
};

The important part is onmessage: the client receives messages whenever the server sends them, without asking. That's the capability ordinary HTTP couldn't give us - the server pushing data to the client in real time over an open connection.

Why WebSockets are used: the benefits

WebSockets earn their place because of what that persistent two-way channel enables:

Where WebSockets are used

WebSockets power the real-time features you use constantly:

The common thread: interactive, real-time, two-way. Whenever both the client and server need to send updates as they happen, with low latency, WebSockets are the natural fit.

A worked example: a chat message's journey

Let me trace one chat message end to end to make the bidirectional, push nature concrete. Alice and Bob are chatting, both with open WebSocket connections to the server.

Alice types "hey" and hits send. Her browser sends the message over her already-open connection - no new connection, no handshake, just the message, instantly. The server receives it, stores it, and determines it's destined for Bob. Crucially, the server then pushes the message down Bob's open connection - Bob's browser didn't ask, didn't poll, didn't request anything. The message simply arrives, and Bob sees "hey" appear in real time. If Bob replies, the same happens in reverse over his connection to Alice.

Notice what made this work: both connections were already open (persistent), the server could send to Bob without Bob asking (server push), and it happened with minimal overhead (no per-message connection setup). Try to build this with plain HTTP and you'd be stuck - the server would have no way to deliver Alice's message to Bob until Bob's browser happened to ask. That gap is exactly what WebSockets close, and a chat app is the canonical demonstration of why they exist.

WebSockets at scale: the connection challenge

The defining operational reality of WebSockets is that every connection stays open, and open connections cost resources. A server holding a WebSocket connection must keep memory and state for it for as long as it's open - possibly hours. This is fundamentally different from ordinary HTTP, where each request is brief and the connection quickly freed.

At small scale this is no issue. At large scale it becomes the central design challenge: a service with a million concurrent users needs a million open connections, which a single server cannot hold. Real systems spread connections across many servers behind load balancers built for long-lived connections, and often dedicate a separate layer whose only job is managing WebSocket connections, decoupled from business logic. There's also routing: if Alice is on server 1 and Bob on server 7, the system needs a way to get Alice's message from server 1 to server 7 to push to Bob - typically via an internal message bus or pub-sub layer between the connection servers. Designing for millions of persistent connections is a real specialty, which is why "design a chat system" is such a rich system design question.

Security: wss and validation

WebSocket connections should be secured, just like HTTP. The secure version uses the wss:// scheme (WebSocket Secure), which encrypts the connection with TLS exactly as https:// does for HTTP - always use wss:// in production so messages can't be intercepted or tampered with. Beyond encryption, because a WebSocket stays open and both sides send freely, the server must authenticate the connection (verify who the client is, usually during or right after the handshake) and validate every message that arrives, since a malicious client could send anything over an open channel. The persistent, two-way nature that makes WebSockets powerful also means the server can't treat the channel as trusted - every incoming message needs the same scrutiny as any other untrusted input.

Keeping connections alive

Persistent connections can silently die - a network blip, a proxy timing out an idle connection - without either side immediately noticing. To handle this, WebSocket systems typically use ping/pong heartbeats: periodically one side sends a small "ping" and expects a "pong" back, confirming the connection is alive. If the pong doesn't come, the connection is treated as dead and re-established. This is the same heartbeat idea used throughout distributed systems to detect failures, applied here to detect dead connections. Combined with client-side reconnection logic (automatically reopening a dropped connection), heartbeats keep real-time features robust against the network hiccups that would otherwise leave a connection quietly broken while the user stares at a frozen screen.

A note on message format

WebSockets carry raw messages, so the application decides the format - commonly JSON for structured data, or binary for efficiency in performance-critical cases like games. There's no built-in structure imposed, so you design your own message protocol on top: how to distinguish a chat message from a typing indicator from a presence update, for instance. This flexibility is powerful but puts the burden on you to define a clear format both sides agree on. Most real-time applications establish a simple convention early - a message type field and a payload - because once many message kinds flow over one channel, a clear protocol is what keeps it manageable.

When NOT to use WebSockets

WebSockets are powerful, but they're not always the right choice:

Interview: WebSockets are the go-to answer for real-time, interactive system design questions - chat, multiplayer, collaborative apps. The strong signal is justifying the choice by the communication pattern: "This needs low-latency two-way communication, so WebSockets - the server pushes new messages instantly and clients send theirs over the same open connection." And knowing when not to use them - choosing SSE for one-way streams, or noting the resource cost of millions of persistent connections - shows the judgment that separates real understanding from naming the trendy option.

A note on alternatives and evolution

WebSockets aren't the only way to achieve real-time, and the ecosystem keeps evolving. For one-way server-to-client streaming, Server-Sent Events are a simpler, lighter alternative that many apps should prefer when they don't need two-way flow. Modern versions of HTTP have introduced their own multiplexing and streaming capabilities that change some of the original performance motivations for WebSockets. And higher-level frameworks and libraries often sit on top of WebSockets, adding automatic reconnection, fallback to long polling, and message-routing conveniences so you don't build those from scratch. None of this displaces WebSockets for their core use case - interactive, low-latency, bidirectional communication - but it's worth knowing that WebSockets are one tool in an evolving real-time toolkit, best chosen specifically when genuine two-way real-time interaction is the requirement, rather than as a default for anything that updates.

The bottom line

A WebSocket is a persistent, bidirectional, full-duplex channel between client and server over a single connection. It starts as an HTTP request that upgrades via a handshake into a long-lived open line, after which both sides can send messages instantly, in either direction, with minimal overhead. It exists because the request-response model of HTTP can't let the server push data to the client in real time - and WebSockets solve that properly, unlike the polling workarounds that came before.

That's why WebSockets are the foundation of real-time interactive apps: chat, games, collaboration, live trading. Use them when you need genuine two-way real-time communication - and reach for lighter options (SSE, polling) when you don't. We cover real-time communication and its trade-offs across System Design Fundamentals.


Go deeper

More articles