Guide

HTTP was built for the client to ask and the server to answer. Many products need the reverse. A chat message should appear the moment it is sent. A ride app should show the car moving. An LLM should stream tokens as it writes them. In each case the server has news, and it has to push that news to a client that did not ask for it.

This topic covers the transport options, from simple polling to WebSockets. It then covers the architecture that delivers messages to millions of open connections: gateways, a connection registry, a pub/sub backbone, heartbeats and resumable reconnects.

Choosing a transport

Short pollingLong pollingSSEWebSocketsWebTransport
DirectionClient pullsClient pulls, server holdsServer to clientBothBoth
Delivery delayUp to the poll intervalNear-instantNear-instantNear-instantNear-instant
Overhead per messageFull HTTP requestFull HTTP requestA few bytes2 to 14 bytesSmall
Reconnect and resumeNot neededManualBuilt inManualManual
Best forRefresh every 30 seconds or moreLegacy fallbackFeeds, notifications, token streamsChat, games, collaborationGames, media, lossy networks

Pick the simplest option that works. Polling is fine when updates are slow. Server-Sent Events fit one-way streams. WebSockets fit two-way traffic with frequent small messages.

Concepts in this topic

Read them in order. Each one builds on the last.

StepConceptWhat it answers
1Polling and long pollingHow do you get updates from a client that only pulls?
2SSE and WebSocketsHow does the server push over a long-lived connection?
3Gateways and connection registryWhich machine holds user 42's connection?
4Fan-out with pub/subHow does one message reach thousands of connected users?
5Connection lifecycleHow do heartbeats, resumes and reconnects avoid losing messages?
6Presence and typingHow do you show who is online without drowning the system?

Common mistakes

  • Using sockets by default. A feed that refreshes every minute does not need a persistent connection.
  • Keeping sockets open in the background on mobile. Phones suspend background apps, and an always-on radio drains the battery. Use platform push for background updates, and treat it as a signal to sync.
  • Shipping gateway code that changes daily. Every gateway deploy disconnects its users. Keep business logic in stateless services.
  • Forgetting reconnects. Clients disconnect constantly. Plan for a resume and a jittered retry from day one.

Key takeaways

  • Short polling is simple but wasteful. Long polling, SSE and WebSockets push updates as they happen.
  • Real-time systems split into thin, stateful connection gateways and stateless application services, linked by pub/sub.
  • Heartbeats detect dead connections, and sequence numbers make reconnects lossless.
  • Presence and typing are ephemeral. Use keys with a TTL, and fan out only to people who can see them.
  • Plan for reconnect storms and deploys, not just steady-state load.

Further learning

Slack's engineering team describes how gateway servers, channel servers and presence servers deliver messages to millions of clients:

Real-time Messaging (Slack Engineering)Did you know that ground stations transmit signals to satellites 22,236 miles above the equator in geostationary orbits, and that those signals are then beamed down to the entire North American subcontinent? Satellite…slack.engineering

Discord's account of scaling Elixir to 5 million concurrent users covers the same gateway design in production:

How Discord scaled Elixir to 5,000,000 concurrent usersHow Discord Scaled Elixir to 5,000,000 Concurrent Usersdiscord.com

Start with polling and long polling to see the simplest option first.