← All posts

Is anyone there? How the web learned to talk back

From polling to WebSockets: the whole story, with diagrams.

How the web went from asking "anything new?" over and over to one open, two-way connection. The tricks that came before, how a WebSocket actually works, and when you should and should not use one.

HTTP was built for documents: the browser asks, the server answers, the conversation ends. That works for pages. It does not work for a chat message, a moving bus on a map or a price that changes every second, where the server has news and the browser has not asked yet.

For about fifteen years the web worked around this with tricks. WebSockets replaced the tricks with a real two-way connection. To see why it matters, it helps to see what came before.

Before WebSockets

Every approach below tries to answer one question: how does the server tell the browser something the moment it happens?

How the web did "real-time" before WebSockets
TechniqueHow it worksThe catch
Short pollingThe browser sends a request every few seconds: anything new?Most answers are "no". Each one costs a full HTTP request with headers, and news waits until the next poll.
Long polling (Comet)The browser asks, and the server holds the request open until there is news or a timeout, then the browser asks again at once.Near real-time, but every message still needs a fresh request, and servers hold many idle requests open.
HTTP streamingThe server never finishes the response and keeps writing to it (the "forever iframe" trick).One way only, fragile through proxies and buffers, and awkward to parse.
Flash and Java socketsA browser plugin opened a raw socket for the page.Needed a plugin; died with Flash.
Server-Sent Events (SSE)The browser opens an EventSource and the server streams text events down one long HTTP response.Server to browser only, text only. The browser still sends anything back with ordinary requests.

Polling and long polling, side by side

With short polling the browser keeps asking on a timer. With long polling the server waits before it answers, so news arrives sooner, but every message still costs a whole new request.

Short polling
BrowserServerGET /updates200 · nothing newwait 5 sGET /updates200 · nothing newwait 5 sGET /updates200 · 1 new messageBrowserServerGET /updates200 · nothing newwait 5 sGET /updates200 · nothing newwait 5 sGET /updates200 · 1 new message
Long polling
BrowserServerGET /updatesserver holds the request…200 · 1 new messageGET /updates (again, at once)server holds the request…200 · 1 new messageBrowserServerGET /updatesserver holds the request…200 · 1 new messageGET /updates (again, at once)server holds the request…200 · 1 new message

Server-Sent Events: one way, built in

Server-Sent Events are part of the HTML standard. The browser opens a connection with new EventSource(url), and the server answers with the content type text/event-stream and keeps writing events to it. The browser reconnects by itself if the connection drops, and sends a Last-Event-ID header so the server can resume.

SSE is a good fit when only the server talks: notifications, a live feed, progress of a long job, or tokens streaming from an AI model. It runs over plain HTTP, so it passes through most proxies. What it cannot do is let the browser talk back on the same connection.

Server-Sent Events
BrowserServerGET /events · Accept: text/event-stream200 · text/event-stream (stays open)data: update 1data: update 2data: update 3browser replies? a separate requestBrowserServerGET /events · Accept: text/event-stream200 · text/event-stream (stays open)data: update 1data: update 2data: update 3browser replies? a separate request

What a WebSocket is

A WebSocket is one long-lived connection between the browser and the server, over which either side can send a message at any time. It was standardised as RFC 6455 in December 2011, and every modern browser supports it.

  • Bidirectional and full-duplexBoth sides can send at the same time. The server does not wait to be asked, and the browser does not open a new request to reply.
  • PersistentOne TCP connection stays open for minutes or hours, so there is no new handshake per message.
  • Low overheadAfter the handshake a message carries a frame header of 2 to 14 bytes, not a full set of HTTP headers.
  • Message-basedData travels as messages, either UTF-8 text or binary, so you are not parsing a raw byte stream.
  • Starts as HTTPThe connection begins as a normal HTTP request on port 80 or 443, which is why it gets through most firewalls.
  • Encrypted when you want itwss:// runs the same protocol over TLS, just as https:// does for HTTP.

The handshake

A WebSocket starts life as an HTTP/1.1 request that asks to switch protocols. If the server agrees, it answers 101 Switching Protocols, and from that moment the same TCP connection speaks WebSocket instead of HTTP.

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

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

The Sec-WebSocket-Accept value proves the server really understood the request: it is the client’s key joined to a fixed string from the standard, hashed with SHA-1 and base64-encoded. It is not security on its own; it only stops a plain HTTP server from being mistaken for a WebSocket one.

WebSocket
BrowserServerGET /live · Upgrade: websocket101 Switching Protocolsone open connection, both waysbus 12 at stop 4subscribe route 7bus 7 at stop 2bus 12 at stop 5pingpongBrowserServerGET /live · Upgrade: websocket101 Switching Protocolsone open connection, both waysbus 12 at stop 4subscribe route 7bus 7 at stop 2bus 12 at stop 5pingpong

Frames, briefly

On the wire, every message is one or more frames. Each frame has a small header with an opcode that says what it carries.

WebSocket frame types (opcodes)
OpcodeFrameUsed for
0x1TextA UTF-8 message, for example JSON
0x2BinaryRaw bytes: images, audio, compact encodings
0x0ContinuationThe next part of a message split across frames
0x8CloseStarts a clean shutdown, with a status code
0x9PingChecks the other side is still there
0xAPongThe reply to a ping

Frames sent from the browser to the server are always masked with a random key. That is not encryption; it stops a malicious page from making the traffic look like something a badly written proxy would cache.

All four, compared

Polling, long polling, SSE and WebSockets
Short pollingLong pollingSSEWebSocket
DirectionClient asksClient asksServer → clientBoth ways
ConnectionNew each timeNew per messageOne, long-livedOne, long-lived
DelayUp to the intervalLowLowLowest
Overhead per messageFull HTTP requestFull HTTP requestSmallSmallest (2–14 byte header)
DataAnyAnyText onlyText or binary
Auto-reconnectn/aYour codeBuilt inYour code
Works through HTTP caches/CDNsYesMostlyMostlyNeeds Upgrade support
Best forRare changesFallbackFeeds, notifications, AI token streamsChat, games, tracking, collaboration

Where WebSockets are used

  • Chat and messagingMessages, typing indicators and read receipts both ways.
  • Live trackingVehicles, deliveries and devices pushing their position every few seconds.
  • Multiplayer gamesPlayer moves going out and the game state coming back many times a second.
  • Collaborative editingMany people editing one document or board and seeing each other’s cursors.
  • Trading and live pricesTickers and order books that change faster than a page could poll.
  • IoT and telemetryDevices streaming readings and receiving commands on the same connection.
  • Live dashboards and opsMetrics, logs and alerts appearing as they happen.

When not to use one

If data changes every few minutes and a short delay is fine, polling is simpler, cacheable and works everywhere. If only the server talks, Server-Sent Events give you reconnection for free over plain HTTP. Reach for a WebSocket when both sides need to talk, often, with as little delay as possible.

What to plan for in production

  • ReconnectionConnections drop on every network change. Reconnect with backoff, and have the client say what it last saw so it can catch up.
  • HeartbeatsSend pings so dead connections are noticed and idle proxies do not cut you off.
  • AuthenticationCheck who the user is during the handshake, and check the Origin header: browsers do not apply the same-origin policy to WebSockets.
  • Message formatAgree a small envelope, for example a type and a payload, and validate every message, especially from devices.
  • Scaling outA connection lives on one server. With several servers, use a shared channel such as Redis pub/sub so a message reaches the right connection.
  • BackpressureA slow client can fall behind. Drop, merge or buffer updates on purpose instead of letting memory grow.

What comes next

WebSockets can also run over HTTP/2 (RFC 8441), sharing one connection with other requests. WebTransport, built on HTTP/3 and QUIC, adds multiple streams and unreliable datagrams for cases like games and media. For most real-time features today, though, a WebSocket is still the simple, well-supported answer.

Keep reading

  • Email & DNS
  • Backend

Have you ever thought how email works?

One click on Send, six hops, five DNS records and a handshake in plain text.

You press Send and a second later it lands on the other side of the world. Here is the whole journey: SMTP, the servers it passes through, and the DNS records (MX, SPF, DKIM, DMARC) that decide whether it reaches the inbox or the spam folder.

  • Backend
  • Architecture

Why your microservices should stop shouting JSON

gRPC and Protocol Buffers in plain words, and where REST still wins.

Why services inside a system often talk gRPC instead of JSON over HTTP, what a .proto file gives you, and where REST still fits.

  • AI Agents
  • Automation

Let the AI draft. Let a human press Send.

Why the smartest AI agents stop exactly one click short.

The most useful AI agents I build do almost everything, then stop one step short. Here is why the last click belongs to a person, and how to design for it.

Have a process worth automating?

Tell me what eats your team's week. I'll tell you what I'd automate first.

Start a project Remote · PrimeX Meta, Dubai · teams across time zones