Skip to main content
Madhukar
All Articles

Realtime Systems: Polling, WebSockets, SSE, and Pub/Sub

July 21, 20268 min read
Fullstack DevelopmentWebSocketsBackendRealtimeSystem Design
Realtime Systems: Polling, WebSockets, SSE, and Pub/Sub

How does WhatsApp deliver a message instantly?

You send a message. Before you’ve even put your phone down, your friend’s phone has already buzzed. No page refresh, no waiting, no visible delay — the message just arrives.

Under the hood, that instant delivery is the result of a deliberate architectural choice, not a given. The default way the web communicates — a client asking, a server answering, then the connection closing — was never built for a server to reach out to you the moment something happens. This guide walks through the four major approaches built to solve that gap: polling, long polling, Server-Sent Events, WebSockets, and the Pub/Sub architecture that often sits behind all of them at scale.

1. What Makes a System “Realtime”?

What realtime means in software systems

A realtime system delivers updates to users with minimal, near-imperceptible delay after an event occurs — the gap between “something happened” and “the user saw it” is small enough to feel instantaneous.

Realtime vs near realtime

Truly “hard” realtime (guaranteed delivery within strict time bounds) is mostly a concern in specialized domains like industrial control systems. Most consumer software — chat apps, live dashboards, notifications — is more accurately near realtime: updates arrive within a second or two, which feels instant to a human even though it isn’t mathematically instantaneous.

Why modern applications need realtime communication

Users increasingly expect information to be current the moment they look at it, not the moment they last refreshed the page — a shift in expectation that traditional request-response alone can’t satisfy well.

Examples

  • Chat applications — messages must appear the instant they’re sent, in both directions
  • Notifications — a like, a comment, an alert should reach the user without them needing to check
  • Live dashboards — stock prices, system metrics, or sports scores updating continuously without manual refresh
  • Ride tracking — a driver’s location updating on the map in near real time as they move
  • Collaborative editing — seeing a teammate’s cursor and edits appear as they type, in tools like shared documents

2. Traditional Request-Response Communication

How HTTP communication normally works

The standard web model: the client sends a request, the server processes it and sends back a response, and the connection is done. The server never initiates contact — it only ever replies to something the client asked first.

Why traditional APIs are not enough for realtime systems

If a new chat message arrives on the server, plain HTTP gives the server no way to push that message to the client — the client would need to ask again before it could find out anything changed.

Limitations of constant refreshing

The obvious workaround — have the client keep asking, over and over — introduces its own set of tradeoffs, covered in depth in the next section: wasted requests, delay between updates, and real load on the server.

User experience challenges

Manually refreshing a page for updates (or waiting on a slow, infrequent auto-refresh) feels clunky and dated compared to the seamless, live experience modern users have come to expect from apps like chat, social feeds, and delivery tracking.

3. Polling

What polling is

Polling has the client repeatedly send requests to the server at a fixed interval — “anything new?” every few seconds — regardless of whether anything has actually changed.

How polling works

Advantages of polling

  • Simple to implement — it’s just repeated, ordinary HTTP requests
  • Works with any standard server setup, no special protocol support needed
  • Easy to reason about and debug

Disadvantages of polling

  • Wastes requests and server resources when nothing has actually changed (the common case)
  • Introduces real delay — an update might occur right after a poll, meaning the client waits nearly the full interval before finding out
  • Doesn’t scale gracefully — more users means proportionally more redundant “anything new?” requests hitting the server, most of which return nothing

When polling is sufficient

For data that changes infrequently and where a delay of tens of seconds is genuinely fine — checking for a background job’s completion status, for instance — polling’s simplicity can outweigh its inefficiency.

Resource utilization considerations

Polling’s cost scales directly with the number of connected clients and how frequently they poll — a large user base polling every few seconds can generate enormous, mostly wasted load compared to the actual rate of real updates.

4. Long Polling

How long polling differs from polling

Instead of the server answering immediately (usually with “nothing new”), long polling has the server hold the request open and only respond once new data actually becomes available — or after a timeout is reached, at which point the client immediately reconnects.

Why long polling was introduced

Long polling was a clever way to approximate server-initiated push using only standard HTTP, before WebSockets existed widely — reducing the wasted “nothing new” round trips of basic polling while still working over ordinary HTTP infrastructure.

Benefits and drawbacks

Benefits: meaningfully lower latency than basic polling, and far fewer wasted “nothing changed” responses. Drawbacks: each held-open connection still consumes server resources while waiting, and the constant reconnect cycle adds overhead and complexity compared to a single persistent connection.

Real-world usage scenarios

Long polling remains useful as a fallback for environments where WebSockets aren’t well supported (certain restrictive networks or older infrastructure) or where a full persistent-connection setup isn’t justified.

5. Server-Sent Events (SSE)

What SSE is

Server-Sent Events let a server push a continuous stream of updates to the client over a single, long-lived HTTP connection — without the client needing to re-request anything.

One-way communication model

SSE is deliberately one-directional: server to client only. The client opens the connection once; the server can then send as many updates as it wants over that same connection, but the client can’t send data back over that same channel.

How servers push updates

The server simply writes new events onto the still-open connection as they occur — the browser’s built-in EventSource API handles receiving and parsing them automatically.

Advantages of SSE

  • Simpler than WebSockets to set up and reason about, since it’s built directly on standard HTTP
  • Automatic reconnection is handled natively by the browser’s EventSource API
  • A natural fit for anything that’s fundamentally one-directional — the server has updates, the client just needs to receive them

Limitations of SSE

  • One-way only — genuinely bidirectional communication (like chat) needs a separate channel for client-to-server messages, or a different technology entirely
  • Historically limited by a maximum number of concurrent connections per browser per domain in older HTTP versions (largely mitigated with HTTP/2)

Suitable use cases

Live notifications, live sports scores, stock price tickers, or any dashboard where the server has ongoing updates to push but the client doesn’t need to talk back over the same channel.

6. WebSockets

What WebSockets are

WebSockets establish a single, persistent, bidirectional connection between client and server — after an initial handshake, both sides can send messages to each other at any time, independently.

Persistent connections

Unlike HTTP’s typical request-then-close pattern, a WebSocket connection stays open for as long as both sides want it to — no repeated reconnecting, no request/response ceremony per message.

Bidirectional communication

This is the key distinction from SSE: both the client and the server can initiate sending a message at any time over the same open connection — essential for anything genuinely two-way, like a chat conversation.

Connection lifecycle

A WebSocket connection moves through: handshake (upgrading from a normal HTTP request), an open, active phase where messages flow freely in both directions, and eventual closure (by either side, or due to a network issue — often followed by a reconnect attempt).

Why chat applications use WebSockets

Chat needs both low latency in both directions and doesn’t fit a clean “server pushes, client just listens” model — a user is both sending and receiving messages continuously, making WebSockets’ true bidirectionality a natural fit.

Performance benefits

Because the connection stays open, WebSockets avoid the repeated overhead of establishing new connections for every message — a real efficiency gain for applications exchanging many small messages frequently, in both directions.

7. Pub/Sub Systems

Producers and consumers

A publisher simply announces “here’s an update for the chat-room-42 channel." Any number of independent subscribers listening to that same channel receive it — the publisher never needs to know how many subscribers exist, or who they are.

Topics and subscribers

Channels (often called topics, echoing the Kafka architecture from earlier in this series) let publishers and subscribers organize messages by category — notifications:user_123, chat:room_42, stock:AAPL — so subscribers only receive what they've actually signed up for.

Decoupled communication

This is Pub/Sub’s core value: publishers and subscribers never communicate directly, and neither needs to know the other exists — new subscribers can be added without any change to the publishing side at all.

Event-driven architecture

Pub/Sub is a natural architectural backbone underneath WebSocket or SSE connections at scale: an event happens somewhere in the backend, gets published to a topic, and a realtime-delivery layer (holding the actual WebSocket/SSE connections) subscribes to that topic and pushes the update out to connected clients.

Real-world examples

A notification service publishing “user 123 got a new like” to a notifications:user_123 topic; a chat backend publishing new messages to a chat:room_42 topic that every connected participant's server instance subscribes to, regardless of which physical server each user's WebSocket happens to be connected through.

8. Comparing All Approaches

Polling vs Long Polling

Long polling reduces wasted requests and lowers latency compared to basic polling, at the cost of holding connections open longer and slightly more implementation complexity.

Long Polling vs SSE

SSE offers a cleaner, standardized way to achieve the same “server pushes updates” goal, using one genuinely persistent connection instead of a repeated hold-and-reconnect cycle — with built-in reconnection handling.

SSE vs WebSockets

SSE is simpler and sufficient for one-directional data (server → client only). WebSockets are necessary the moment the client also needs to send data back over that same live connection.

WebSockets vs Pub/Sub

These aren’t really competitors — WebSockets are a connection mechanism between one client and one server; Pub/Sub is a messaging architecture for routing events to the right subscribers, often used together: Pub/Sub decides who should receive an update, and WebSockets (or SSE) deliver it to the browser.

Performance and scalability tradeoffs

9. Building Realtime Systems at Scale

Handling thousands of connections

Every open WebSocket or SSE connection consumes server memory and resources for as long as it stays open — a chat app with a million concurrently connected users needs infrastructure specifically designed to hold that many long-lived connections efficiently, which is a different challenge than handling a similar volume of short-lived HTTP requests.

Message delivery

At scale, a single server instance rarely holds every connected user’s socket — a message published for one user might need to be routed to whichever specific server instance currently holds that user’s live connection, which is exactly the coordination problem Pub/Sub (Section 7) solves.

Reliability considerations

Networks are unreliable — connections drop, servers restart. Realtime systems at scale need reconnection logic, and often a way for a reconnecting client to catch up on anything it missed while briefly disconnected.

Scaling horizontally

Because WebSocket/SSE connections are stateful and long-lived, horizontally scaling a realtime system (adding more servers) requires a shared coordination layer — commonly a Pub/Sub system — so a message published anywhere can reach a subscriber connected to any server instance.

Managing connection state

Systems need to track which users are currently connected, to which server instance, and clean up that state promptly when connections close — stale connection tracking can silently cause missed message delivery.

10. Choosing the Right Approach

Chat applications

Need genuine bidirectionality and low latency — WebSockets are the natural fit, typically backed by Pub/Sub for delivering messages across multiple server instances.

Notification systems

Often one-directional (server informs the client something happened) and doesn’t require the client to respond over the same channel — SSE is frequently sufficient, and simpler to operate than full WebSockets.

Live sports scores

Server-driven, one-directional updates at a moderate frequency — a strong fit for SSE, or even well-tuned polling if near-instant delivery isn’t strictly required.

Stock market dashboards

High-frequency, server-driven updates where low latency genuinely matters — WebSockets or SSE both apply, with WebSockets often preferred when the same connection also needs to send user actions (like placing an order) back to the server.

Collaborative applications

Multiple users editing together need low-latency, bidirectional updates flowing constantly in both directions — WebSockets are the standard choice here, since both directions matter continuously, not just server-to-client.

IoT systems

Depends heavily on the specific device and network constraints — some IoT scenarios use lightweight Pub/Sub-based protocols (like MQTT) over persistent connections, prioritizing efficiency on constrained devices over raw simplicity.

Final Takeaway

None of these approaches is simply “better” than the others in isolation — each answers a different version of the same question: how much does the server need to reach out, how often, and does the client need to talk back? Polling is the simplest, blunt-force answer. Long polling refines it. SSE gives the server a clean, standardized way to push one-directional updates. WebSockets add true bidirectionality for conversations that flow both ways. And Pub/Sub is the architecture that, at real scale, decides who should receive a given update in the first place — often sitting quietly behind whichever delivery mechanism your users actually connect through.

Frequently Asked Questions

Is WebSockets always the best choice for realtime features?

> No — it’s the best choice specifically when genuine bidirectional, low-latency communication is required, like chat. For simpler, one-directional needs like notifications or live scores, SSE is often simpler to build and operate while delivering a similar user experience.

Can SSE be used for a chat application?

> Not on its own — SSE only pushes data from server to client. A chat app would still need a separate mechanism (like a regular HTTP request) for the client to send messages, making WebSockets a cleaner single-connection solution for that specific use case.

Is Pub/Sub a replacement for WebSockets or SSE?

> No — they solve different problems. Pub/Sub is a messaging architecture for routing events to the right subscribers, often across multiple servers; WebSockets and SSE are the mechanisms that actually deliver those events to a user’s browser. They typically work together.

Is polling ever the right choice in a modern application?

> Yes, when delay of tens of seconds (or more) is genuinely acceptable and the implementation simplicity outweighs the inefficiency — checking a background job’s status is a common, reasonable example.

Originally published by Mr Madhukar

Read the complete article on Medium with full formatting & reader responses.