AlgoMaster Logo

Real-time Updates in System Design

High Prioritymedium18 min readUpdated June 17, 2026
AI Mock Interview

Practice this topic in a realistic system design interview

Listen to this chapter
Unlock Audio

Modern applications often need to show users fresh information without waiting for a page refresh. When a friend sends a message, you expect to see it quickly. When a driver moves, the map should update every few seconds. When a notification is triggered, it should arrive while it is still useful.

These experiences are usually called real-time updates, but "real-time" is not one requirement. It might mean 100 ms for a collaborative editor, 1 second for chat, 5 seconds for driver tracking, or 30 seconds for a dashboard. The target matters because it determines the right transport, cost, and correctness model.

The traditional request/response model is not enough by itself. A client makes a request, the server responds, and the exchange is done. If something changes on the server afterward, the client needs another request or an open channel to learn about it.

This chapter covers the common approaches: short polling, long polling, Server-Sent Events, and WebSockets. The interview skill is not memorizing which one is "best." It is matching latency, directionality, delivery guarantees, scale, and operational complexity to the product requirement.

Where This Pattern Shows Up

Real-time updates appear across a wide range of systems:

ProblemWhy Real-time Matters
Design Chat SystemMessages need low latency, typing indicators need to feel live
Design Uber/LyftDrivers move continuously, riders need to see position updates every few seconds
Design Trading PlatformPrice feeds need low latency and clear ordering semantics
Design Collaborative EditorMultiple users editing the same document need low-latency sync
Design Notification SystemAlerts lose value if they arrive minutes after the triggering event
Design Live Sports AppFans expect scores and play-by-play updates as they happen

The four common approaches form a spectrum:

  • Short Polling: Client repeatedly asks "any updates?" Simple, but can waste requests.
  • Long Polling: Server holds the request open until there is data or a timeout. More efficient, still HTTP.
  • Server-Sent Events (SSE): Server pushes updates over a persistent one-way HTTP stream.
  • WebSockets: Full two-way communication over a persistent connection.

Questions to Clarify First

Before choosing a mechanism, clarify the requirements:

QuestionWhy It Matters
What latency is required?"Real-time" could mean milliseconds, seconds, or "eventually visible"
Is communication one-way or bidirectional?Server-to-client streams fit SSE; frequent two-way interaction points to WebSockets
How many clients and messages per second?Connection count and message fanout often dominate cost
Are messages durable?Pub/sub can wake live clients, but replay needs a log, database, or stream
Is ordering required?Chat rooms, document edits, and trades need sequence IDs or per-topic ordering
What happens on reconnect?Clients need resume tokens, deduplication, and backoff with jitter
Can updates be dropped or coalesced?Presence, typing, and prices can often drop old updates; chat messages usually cannot

This framing prevents a common interview mistake: picking WebSockets first, then discovering later that the real problem was replay, ordering, fanout, or slow clients.

Each approach sits at a different point on the simplicity-vs-capability spectrum. The sections that follow cover them one at a time.

Approach 1: Short Polling

Short polling is the simplest approach, and often the first thing that comes to mind. The client asks "anything new?" at regular intervals, and the server responds with whatever it has.

Wait 5 secondsWait 5 secondsAny updates?NoAny updates?NoAny updates?Yes, here's the data!ClientServer
8 / 8
algomaster.io

How It Works

The client sets a timer, say every 5 seconds, and sends an HTTP request when it fires. The server checks for new data and responds with updates or an empty response. The client processes any data, waits for the next interval, and repeats.

The approach is predictable and easy to reason about, but it does not scale gracefully when many clients poll frequently.

The Fundamental Trade-off

Short polling forces you into an uncomfortable choice between latency and resource consumption:

Poll Every 1 SecondPoll Every 30 Seconds
LatencyUpdates arrive quicklyUpdates delayed up to 30 seconds
Request Volume3,600 requests/hour per client120 requests/hour per client
Server LoadServer under constant loadServer load manageable
BatteryHigh battery drain on mobileBattery-friendly

Poll frequently and you get faster updates but put heavy load on your servers. Poll less often and you save resources but users wait longer for new data. There is no middle ground that escapes the trade-off: lower latency means more requests unless you switch to a different approach.

The numbers add up quickly. With a 5-second polling interval and 1 million active clients, that is roughly 200,000 requests per second, and many of those requests return nothing useful. That is a large infrastructure cost for empty responses.

Pros

  • Simple to implement with standard HTTP requests on a timer
  • Works everywhere, every browser and every HTTP client supports it
  • Stateless on the server side, which makes horizontal scaling straightforward
  • Easy to debug because each request-response cycle is independent

Cons

  • Most requests return nothing, wasting bandwidth and server resources
  • Updates are delayed by half the polling interval on average
  • At scale, many clients polling frequently create high server load
  • Drains mobile batteries with constant network activity

When Short Polling Makes Sense

Despite its limitations, short polling remains a reasonable choice in specific scenarios. It works well for email inbox checks, dashboard refreshes, background sync, and status page monitoring, cases where updates are infrequent and a few seconds of delay is fine.

It is a poor fit for chat, live location tracking, trading platforms, and multiplayer games, where latency is tight or updates are continuous.

If updates are infrequent and a delay of a few seconds is acceptable, short polling keeps your architecture simple. But if the latency target is tight or the client count is large, you need something better.

Approach 2: Long Polling

Long polling changes the basic polling idea. Instead of responding with "nothing new," the server holds the connection open and waits until it has something to send.

This small change makes a significant difference in how the system behaves.

No data yet, hold connection...Still waiting...Process the updateHold connection again...Any updates? (Request 1)New data arrives!Here is your update!Any updates? (Request 2)ClientServerDataStore
8 / 8
algomaster.io

How It Works

The client sends an HTTP request asking for updates. If the server has new data, it responds. If not, it holds the connection open and waits, typically with a timeout of 30 to 60 seconds.

When new data arrives, the server responds to the waiting request. The client processes the data and opens a new request. This creates a continuous loop where updates arrive quickly without constant empty polling.

The key insight is that instead of the client asking "is there anything new?" over and over, it asks once and waits for the answer. The server only responds when it has something meaningful to say.

Visualizing the Difference

The contrast with short polling becomes clear when you look at the request patterns side by side:

In this example, short polling sends 6 requests in 30 seconds, most returning empty. Long polling sends fewer requests, and each one either returns meaningful data or times out.

The Server-Side Challenge

The challenge with long polling is what happens on the server while it waits. You cannot have a thread sitting in a loop checking for updates. That would waste CPU and limit how many connections you can handle.

Production implementations rely on event-driven architectures and notification systems:

When a request comes in, the handler registers interest in a topic and yields control. It should not busy-wait or block a thread per client. When a new update is published, the relevant waiting handlers wake up and respond.

Pub/Sub or Stream can wake live handlers, but it is ephemeral. If clients need replay after disconnects, use a durable log, stream, or database-backed cursor.

Pros

  • Low-latency delivery without constant empty polling
  • Far fewer wasted requests compared to short polling
  • Works through firewalls and proxies since it is still standard HTTP
  • Simpler to implement than WebSockets, no special protocol to learn
  • Runs on standard HTTP load balancers and reverse proxies once their idle timeouts are tuned above the poll hold time

Cons

  • Each waiting client holds a server connection open, which consumes resources
  • Requires async server frameworks to handle thousands of concurrent connections efficiently
  • After each response, the client must establish a new request, adding latency
  • Timeout handling requires careful thought, especially for mobile clients with unstable connections
  • Message ordering can be tricky when responses and new requests overlap
  • CDNs do not help, held-open responses are dynamic and uncacheable, and CDN buffering can break the held connection

When Long Polling Shines

Long polling occupies a useful middle ground. It delivers near real-time updates while staying within the familiar HTTP paradigm.

Long polling works well for notification systems, activity feeds, moderate-scale chat, and progress updates, any application that needs real-time delivery but does not require the client to send frequent messages. Consider alternatives once message frequency is high, the interaction becomes bidirectional, or you need extreme scale. It is a reasonable intermediate step before committing to the complexity of WebSockets.

Approach 3: Server-Sent Events (SSE)

Server-Sent Events use a different approach. Instead of the client asking for updates repeatedly, it opens a single long-lived connection and the server pushes data through it whenever something changes.

This is closer to how we intuitively think about real-time: the server notifies you when something happens rather than you asking "has anything changed?" over and over.

Single HTTP connection stays openConnection stays open until timeout or disconnect...Open SSE connectionPrice changedevent: price-updatedata: {symbol: AAPL, price: 150.25}New trade executedevent: tradedata: {symbol: AAPL, shares: 100}Price changedevent: price-updatedata: {symbol: AAPL, price: 150.50}ClientServerDataSourceClientServerDataSource
9 / 9
algomaster.io

How It Works

The client opens a connection using the browser's built-in EventSource API. The server responds with a special content type (text/event-stream) and keeps the connection open. From that point on, the server can push events at any time. The client registers handlers for different event types and processes them as they arrive.

SSE keeps the client-side code small. The browser handles basic connection management, reconnection attempts, and event parsing. Your application still needs to decide how to resume, deduplicate, and handle stale state after a reconnect.

The Event Format

SSE uses a simple text-based protocol. Each message is a series of field-value pairs separated by newlines:

FieldPurpose
eventNames the event type so clients can route to specific handlers
idUnique identifier for resumption after disconnection
dataThe actual payload, usually JSON
retryTells the client how long to wait before reconnecting

The text-based format makes SSE easy to debug. You can see exactly what the server is sending by watching network traffic.

Automatic Reconnection

A useful part of SSE is browser-managed reconnection. When the connection drops, whether from network issues, server restarts, or anything else, the browser attempts to reconnect.

Connection drops!Wait retry interval...Resume from ID 102Connectevent: update, id: 100event: update, id: 101event: update, id: 102ReconnectLast-Event-ID: 102event: update, id: 103event: update, id: 104ClientServer
10 / 10
algomaster.io

The browser sends the Last-Event-ID header when reconnecting, allowing the server to resume from a known event ID if the server keeps a replayable event log. This gives you a useful resume mechanism, but it is not durable delivery by itself. The server must store recent events, handle gaps, and deduplicate on the client when needed.

Pros

  • Native browser support through the EventSource API, minimal client code needed
  • Automatic reconnect attempts and Last-Event-ID support
  • Text-based format makes debugging straightforward
  • Works with many HTTP load balancers and proxies when streaming timeouts and buffering are configured
  • Lighter weight than WebSockets, both in protocol complexity and server resources

Cons

  • One-way only, the server can push to the client but not vice versa
  • Over HTTP/1.1, browsers cap connections per domain at around 6, so several SSE streams on one page can starve other requests; HTTP/2 multiplexing largely removes this since many streams share one connection
  • The native EventSource API cannot set custom headers, so auth usually rides on cookies or a query-param token rather than an Authorization header
  • Text-only protocol, binary data requires Base64 encoding which adds overhead

SSE vs Long Polling

SSE and long polling look similar, since both hold connections open, but they differ in one important way:

Long polling creates a new HTTP request after each response. SSE streams multiple updates over a single connection. This makes SSE more efficient for frequent server-to-client updates and reduces the gap between responses where messages can be missed unless you use cursors.

When SSE Fits

SSE fits well when data flows primarily from server to client: stock price tickers, live sports scores, notification streams, build and job progress, and social media feeds. It is a weaker fit for real-time chat, multiplayer games, and collaborative editing, where both sides send messages frequently and WebSockets serve better.

If the client rarely needs to send data, or when a normal HTTP POST is enough, SSE gives you server push with less operational complexity than WebSockets. Many teams default to WebSockets when SSE would serve them better.

Approach 4: WebSockets

WebSockets provide bidirectional communication where both client and server can send messages over a single persistent connection.

While SSE gives you server-to-client push, WebSockets give you a two-way channel. This is useful when both sides send frequent messages, such as chat, collaboration, games, and interactive trading workflows.

par[Bidirectional Communication]WebSocket connection establishedEither side can send anytimeHTTP Upgrade Request101 Switching ProtocolsUser starts typingOther user's messageUser sends messageDelivery confirmationUser 2 is typing...Another messageClientServer
10 / 10
algomaster.io

How It Works

The connection begins life as an HTTP request. The client sends an upgrade request asking to switch protocols. If the server agrees, it responds with "101 Switching Protocols" and from that moment on, both sides speak WebSocket instead of HTTP.

Once established, either side can send messages. There is no request-response pattern anymore. The client can send while the server is sending, and messages can flow in both directions over the same connection.

The Protocol Upgrade

The transition from HTTP to WebSocket happens through a handshake:

Phase 1: HTTP HandshakePhase 2: WebSocket CommunicationGET /chat HTTP/1.1Upgrade: websocketSec-WebSocket-Key: ...HTTP/1.1 101 Switching ProtocolsSec-WebSocket-Accept: ...WebSocket frameWebSocket frameWebSocket frameWebSocket frameClientServer
8 / 8
algomaster.io

After the handshake, messages are exchanged as WebSocket frames. Compared with repeated HTTP requests, WebSockets avoid per-request headers and can be more efficient for high-frequency messaging. The exact frame overhead depends on payload length and client-side masking.

Why WebSockets Are Different

The key difference between WebSockets and the HTTP-based options is the communication model:

AspectHTTP-based ApproachesWebSocket
InitiationClient initiates every exchangeEither side can initiate
PatternRequest/ResponseNo request/response pattern
ConnectionRequest/response or HTTP streamLong-lived upgraded connection
OverheadHeaders on every requestLower per-message overhead

With HTTP, every exchange starts with the client. Even with SSE, the client opens the connection and the server responds. With WebSockets, the server can send a message to the client at any time without a new request. This enables patterns like typing indicators, presence updates, and real-time collaboration that would be awkward with request/response HTTP.

The Scaling Challenge

WebSockets introduce a scaling complexity that does not exist with stateless HTTP. Each client maintains a persistent connection to a specific server, and those connections are not free. Every open connection holds a socket (a file descriptor) plus send and receive buffers, so memory and the operating system's file-descriptor limit, not CPU, usually set the ceiling.

The default ulimit of 1024 file descriptors per process must be raised before a server can hold meaningful numbers. A reasonable rule of thumb is tens of thousands of idle connections per modern server node.

Tuned setups running event-driven stacks can reach hundreds of thousands to around a million on a single box, with active message traffic lowering that figure.

The practical takeaway for an interview is that you size a WebSocket tier by connection count, not request rate, and add nodes as the connection total grows.

Holding all those connections raises a second problem: what happens when Client A, connected to Server 1, wants to send a message to Client B, who is connected to Server 2?

The common solution is a message bus. When Alice sends a message, Server 1 publishes it to a shared bus, and the bus delivers it to the server holding Bob's connection. There are two ways to wire this up.

The simplest is broadcast: every server subscribes to the same topic, receives every message, and drops the ones for users it does not hold. This is easy to build but wastes work, since each message wakes every node. The alternative is targeted routing: look up which server owns Bob and publish only to that server's channel.

Targeted routing scales better but needs a connection registry, which is the topic of the next section. Either way, Pub/Sub or Stream can work for ephemeral presence or typing events; durable messages usually need Kafka, a database outbox, or another replayable log.

This architecture works, but it adds operational complexity. You need to manage the message bus, handle its failure modes, and design your channel structure thoughtfully.

Connection State Management

Targeted routing depends on knowing where each user is connected, so it requires tracking connection state. With HTTP, each request is independent. With WebSockets, you need a registry that maps each user to the server holding their connection, and the message bus uses that map to deliver only to the right node instead of broadcasting to all of them.

You need to handle what happens when a server crashes, when clients reconnect to different servers, and when the connection registry gets out of sync with reality. Use heartbeats, TTLs, and cleanup on disconnect so stale registry entries do not route messages to a server that no longer holds the connection.

Pros

  • True bidirectional communication, either side can send at any time
  • Low latency with lower per-message overhead than repeated HTTP requests
  • Efficient binary framing reduces bandwidth usage
  • Good fit for high-frequency, interactive applications

Cons

  • More complex than HTTP-based approaches to implement and operate
  • Scaling requires additional infrastructure like message buses
  • Stateful connections are inherently harder to manage than stateless HTTP
  • Some corporate proxies and firewalls block WebSocket traffic
  • The browser WebSocket API does not reconnect automatically; implement it yourself or use a client library
  • Debugging is harder since you cannot inspect individual request/response pairs

When WebSockets Are Worth the Complexity

WebSockets make sense when you need bidirectional, high-frequency communication. Before choosing them, check whether the client needs to send messages frequently, or whether SSE with occasional HTTP POSTs would work.

Chat applications, multiplayer games, collaborative editing, and interactive trading platforms are strong fits because both sides send messages constantly. For news feeds, notifications, live scores, or progress tracking, the flow is mostly one direction, so SSE is usually simpler and sufficient.

Comparing All Four Approaches

With each approach covered in detail, the table below puts them side by side across the dimensions that matter when choosing one.

AspectShort PollingLong PollingSSEWebSocket
CommunicationClient-initiated pollingClient-initiated waiting requestServer-to-client streamBidirectional
LatencyDepends on polling intervalLow when a request is waitingLowLow
Request overheadHTTP request each pollHTTP request after each response or timeoutSingle persistent streamSingle upgraded connection
Server complexitySimplestModerateModerateHighest
Scaling complexityEasy (stateless)MediumMediumHard (stateful)
ReconnectionNext pollManual loopBrowser reconnects; app handles resumeManual or library-managed
Browser supportUniversalUniversalModern browsersModern browsers
Firewall friendlyYesYesYesSometimes blocked
Binary dataVia encodingVia encodingVia encodingNative support

Choosing the Right Approach

The decision tree for selecting an approach is straightforward once you separate latency, directionality, and scale:

The key questions to ask:

  1. What latency is acceptable, and at what scale? If a few seconds of delay is fine and the client count is modest, short polling may be enough. With a large client base, the volume of mostly-empty requests gets expensive even when the latency target is loose, so long polling or SSE is usually the better fit despite the relaxed deadline.
  2. Does the client send frequent upstream messages? If yes, WebSockets usually fit best.
  3. Is the stream mostly server-to-client? If yes, SSE is often simpler than WebSockets.
  4. Do you need replay, ordering, or durability? The transport alone does not solve those; use sequence IDs, cursors, and a durable event source.

Recommendations by Use Case

A few rows below look like they break the "seconds of delay is fine" rule. Public tickers and live scores could tolerate a short delay, yet they land on SSE rather than short polling.

The reason is the scale branch in the tree above: these feeds serve a large audience, so the flood of mostly-empty short-polling requests costs more than a single server-to-client stream, even though the latency target is loose.

Use CaseRecommended ApproachWhy
Email inbox updatesShort pollingUpdates every minute is fine, simplicity wins
Dashboard metricsShort polling or SSEDepends on freshness requirements
Notification systemSSEServer push, built-in reconnection
Activity feedSSEContinuous stream of updates, one direction
Public stock price tickerSSEFrequent server-to-client updates
Live sports scoresSSEReal-time server push
Build/CI progressSSEProgress updates flow one way
Basic chatLong polling or SSE + POSTWorks for moderate scale
Real-time chatWebSocketTyping indicators, read receipts, high frequency
Multiplayer gamesWebSocketLow latency bidirectional required
Collaborative editingWebSocketContinuous bidirectional sync
Interactive tradingWebSocketBidirectional low-latency workflow

Implementation Best Practices

Regardless of which approach you choose, certain problems appear in every real-time system. Handling them well is the difference between a production-ready system and a fragile prototype.

Reconnection with Exponential Backoff

Connections will drop. Mobile users switch between WiFi and cellular. Servers restart for deployments. Network equipment fails. Your system must handle disconnection gracefully.

The standard approach is exponential backoff with jitter:

Start with a short delay (1 second), double it on each failure, and cap at a reasonable maximum (30 seconds). Add random jitter to prevent thundering herd problems when many clients reconnect simultaneously after a server restart. Reset the delay counter after a successful connection.

Heartbeats for Connection Health

A quiet connection and a dead connection look identical from the network perspective. Without active probing, you cannot tell if the other side is still there.

Connection established30 seconds of silence...30 more seconds...Server crashed!No PONG received...Timeout! Reconnect.MessageResponsePINGPONGPINGClientServer
11 / 11
algomaster.io

Send periodic pings, every 30 seconds is a reasonable default, and expect a response within a timeout window. If no response arrives, assume the connection is dead and initiate reconnection. This catches scenarios like server crashes, network partitions, and zombie connections that TCP keepalives might miss.

Message Ordering and Deduplication

In distributed systems, messages can arrive out of order or be delivered multiple times. This is especially common after reconnections when the client might request a replay of recent messages.

Assign sequence numbers or unique IDs to messages. Track the last processed ID on the client. Buffer out-of-order messages until gaps are filled. Detect and discard duplicates. For SSE, the event ID mechanism helps the client tell the server where to resume, but the server still needs a replayable event source.

Backpressure and Flow Control

Sometimes clients cannot keep up with the rate of incoming messages. A mobile device on a slow connection, a browser tab in the background, or a client doing expensive processing can all fall behind.

Monitor send buffer sizes. When a client falls behind, you have choices: drop non-critical messages, aggregate multiple updates into one, or disconnect the client entirely. The best choice depends on the use case. A stock ticker might drop intermediate price updates and send only the latest.

A chat application might need to deliver every message and should disconnect clients that fall too far behind.

Compression for High-Volume Connections

For connections that carry significant data volume, per-message compression can reduce bandwidth substantially. WebSocket supports the permessage-deflate extension, which compresses each message individually. Most WebSocket libraries support this with a configuration flag.

The trade-off is CPU usage for compression and decompression. For text-heavy payloads like JSON, compression can reduce size substantially. For already-compressed data like images, it provides little benefit. Enable it selectively based on payload characteristics and CPU headroom.

Authentication on Long-Lived Connections

Per-request HTTP auth is simple: every request carries a token or cookie and the server checks it each time. Long-lived connections break that model. The client authenticates once at connect time, but the connection can stay open for hours, long enough for the token to expire while the stream is still live.

You cannot re-check a header that is never sent again.

The common pattern is to authenticate during the handshake, then keep the session valid over time. When the token nears expiry, the client sends a refreshed token as an in-band message, or the server closes the connection and the client reconnects with a fresh token. Either way, the connection's authorization is re-established rather than assumed to last forever.

Three security concerns deserve explicit attention:

ConcernRiskMitigation
Transport encryptionTokens and payloads sent in clear textUse WSS for WebSockets and HTTPS for SSE, never plain ws:// or http://
Cross-site hijacking (CSWSH)A malicious page opens a WebSocket to your server, and the browser attaches the user's cookies automaticallyValidate the Origin header on the handshake and prefer an explicit token over cookie-only auth
Token leakageSSE's EventSource cannot set an Authorization header, so tokens often ride in the query string and land in access logsUse short-lived tokens, or pass auth via a cookie scoped to the streaming endpoint

The hijacking case is easy to overlook. The browser's same-origin policy does not block the WebSocket handshake, and it sends cookies with it, so cookie-only auth lets any origin open an authenticated socket. Checking the Origin header closes that gap.

Load Balancing and Zero-Downtime Deploys

Stateless HTTP lets a load balancer send each request to any node. Long-lived connections do not move once established, which changes how the tier in front of them behaves.

First, the load balancer has to understand the connection. A WebSocket starts as an HTTP request with an Upgrade header, so the balancer must either operate at layer 7 and pass the upgrade through, or run at layer 4 as a plain TCP proxy.

Some older proxies strip the upgrade and silently downgrade the connection, which is a common cause of "WebSockets work locally but not in production." Idle timeouts matter too: a balancer that closes quiet connections after 60 seconds will kill an otherwise healthy stream, so heartbeats double as keepalives that reset that timer.

Second, deploys are disruptive in a way they are not for stateless services. Replacing a node drops every connection it holds at once, and those clients reconnect within seconds, all at the same time.

The mitigations are connection draining (stop accepting new connections on a node, then give existing ones a grace period to finish or move before shutdown), staggered rollouts so only a fraction of connections drop at a time, and client-side exponential backoff with jitter so the reconnections spread out instead of arriving in a single burst.

Real-World Examples

The four approaches are not academic. The systems people use every day pick among them based on exactly the trade-offs covered here: directionality, message frequency, and scale.

SystemTransportWhy
SlackWebSocketClients hold a persistent connection for real-time events (messages, presence, typing), all of which flow in both directions at high frequency
DiscordWebSocket gatewayA single gateway connection carries events, with heartbeats for health and sequence numbers plus a resume protocol to replay missed events after a drop
WhatsAppPersistent socketMobile clients keep a long-lived connection (historically a customized XMPP over TCP) so messages push instantly; WhatsApp Web uses WebSocket
FigmaWebSocketMultiplayer editing needs continuous two-way sync of document changes between every connected client and the server
Coinbase / BinanceWebSocket feedsPublic market-data APIs stream order-book and trade updates, mostly server-to-client but exposed over WebSocket for low latency and subscription control
LLM chat UIs (ChatGPT and similar)SSEToken-by-token streaming is one-directional server-to-client, so SSE is a natural fit and avoids the overhead of a full WebSocket

Two patterns are worth calling out. Discord is a clean example of the reliability machinery from earlier sections in production: a WebSocket carries the live stream, but heartbeats detect dead connections and a sequence-number-plus-resume protocol replays what was missed, because the transport alone does not guarantee delivery.

The LLM streaming case shows the opposite lesson, that the newest real-time feature most engineers have shipped recently, streaming model output, uses SSE rather than WebSocket, precisely because the data only flows one way.

Beyond These Four Approaches

Short polling, long polling, SSE, and WebSockets cover the common cases, but two related technologies come up often enough that you should know where they fit.

Push notifications (APNs and FCM)

None of the four approaches work when a mobile app is backgrounded or closed, because the operating system suspends the app and tears down its connections to save battery. Delivering an alert in that state requires a platform push service: Apple Push Notification service or Firebase Cloud Messaging.

The app server hands the message to APNs or FCM, which maintains its own connection to the device and wakes the app. Real apps combine the two models: a live connection while the app is in the foreground, and push notifications when it is not.

WebRTC

When you need the lowest possible latency or direct peer-to-peer media, such as video calls, voice, or screen sharing, WebRTC is the tool. It establishes a direct connection between browsers (falling back to relays when network conditions require), typically over UDP, which trades guaranteed delivery for speed.

It is more complex to set up than the approaches in this chapter and is usually reserved for real-time audio and video rather than general data updates.

Both of these complement the four core approaches rather than replace them, and a full system often uses several together.

Key Takeaways

Real-time updates are now expected in many applications. Users expect timely feedback, whether they are chatting with friends, tracking a delivery, or monitoring a build pipeline.

The four approaches we covered form a progression from simple to sophisticated:

Key principles to remember

  1. Start with requirements. Define latency, directionality, message rate, fanout, ordering, and replay before choosing a transport.
  2. Start simple when it fits. If short polling meets your requirements, use it. The simplest solution that works is often the right solution.
  3. SSE is underrated. If data flows primarily from server to client, SSE is simpler than WebSockets and gives browser-level reconnect support.
  4. WebSockets are powerful but complex. Reserve them for cases that need bidirectional, high-frequency communication. The scaling and operational complexity is significant.
  5. Transport is not delivery semantics. For reliable delivery, ordering, and replay, add sequence IDs, durable logs, cursors, deduplication, and backpressure.
  6. Plan for failure. Connections will drop. Implement reconnection with exponential backoff, heartbeats for health detection, and message ordering for reliability.

The best approach is the one that solves your problem with the least complexity. Start with simpler solutions and evolve only when you have evidence that you need more capability.

Quiz

Real-time Updates Quiz

20 quizzes