Choosing a Real-Time Transport? Here's What Actually Matters at the Backend
Most articles on this topic end up being a table comparison. Polling is slow. SSE is one-way. WebSockets are the "real" answer. Close the tab, problem solved.
But that framing sidesteps the question practitioners actually face: not which protocol is theoretically best, but which one holds up when the data volume goes nonlinear, the backend is stateless, and the client is three tabs open on someone's trading dashboard.
Let's go deeper.
Polling Is Not Dead, It's Just Expensive in the Wrong Places
Long polling gets written off fast. But in markets where events are irregular -- think infrequent order fills or low-frequency sports scores -- it can be exactly right. The cost isn't the protocol, it's the mismatch. If you're polling every 500ms against a system where meaningful state changes happen every 10 seconds, you're burning connections for no reason.
Where polling genuinely breaks down is high-frequency, continuous data: order book updates, live price feeds, sensor streams. There, the overhead compounds. You're paying reconnect and serialization cost on every cycle, and your backend is fielding requests that arrive regardless of whether anything changed.
SSE Has a Specific, Underappreciated Sweet Spot
Server-Sent Events get overlooked because they're unidirectional. But for a lot of real-time display use cases, that's fine -- the client doesn't need to send anything, it just needs to receive. SSE runs over plain HTTP, works naturally through load balancers that WebSockets can complicate, and auto-reconnects without any client-side logic.
The real limitation isn't the unidirectional constraint. It's that SSE connections are per-tab. Open four tabs of the same market dashboard and you've got four separate streams, four separate connections to your backend, all duplicating the same data. That's where the BroadcastChannel API gets interesting: you can run SSE on one tab, then fan out state to siblings using BroadcastChannel in the browser. One stream does the work, all tabs stay in sync. It's a small trick with a real multiplier effect on connection overhead.
WebSockets: Right Tool, Often Over-Applied
WebSockets are the correct choice when you have genuine bidirectional, low-latency requirements: trading engines where the client sends orders, collaborative editors where keystrokes go upstream, anything that isn't just display. The protocol is built for that and it shows.
The over-application happens when teams reach for WebSockets because they feel like the "serious" option, then discover the operational complexity that comes with persistent connections at scale. Long-lived stateful connections don't fit cleanly behind standard HTTP load balancers. Session affinity, connection draining during deploys, reconnect storms when a server restarts -- none of these are unsolvable, but they add surface area that SSE or a well-designed polling scheme simply doesn't have.
The Real Design Decision Is About Your Data Model, Not the Protocol
Here's what actually changes the answer: is your data stream event-driven (a thing happened, push it) or query-driven (what's the current state, fetch it)?
For event-driven streams -- new trade, new block, new score -- push protocols make sense. The server knows when something happened and should be the one to initiate.
For query-driven state -- give me the current order book -- polling or request-response can be cleaner, because you're essentially reading a snapshot, not subscribing to a diff stream.
Where things get complicated is when you need both: a live snapshot on connect followed by incremental diffs. That's where most real-time infrastructure actually lives. You need to handle the initial hydration separately from the ongoing stream, and the protocol choice has to support both modes without a gap where events get dropped.
Backpressure Is the Silent Failure Mode
Whichever transport you pick, the problem that kills real-time systems in production isn't the protocol -- it's backpressure. If the upstream data rate exceeds what the consumer can process, you need somewhere for the pressure to go.
Polling absorbs some of this naturally: the client controls the interval. SSE has no native flow control, so the server needs to rate-limit or buffer upstream. WebSockets have the same problem at higher velocity. If you're building against a stream that can spike -- market open volatility, a major protocol event, halftime refresh -- you need an explicit strategy for what happens when the backend is producing faster than the client can consume. Drop? Buffer? Downsample? That decision matters more than which protocol you're using to deliver the data.
What Actually Matters When You're Picking
A few questions that cut through the noise faster than any comparison table:
- Does your client need to send data upstream? If yes, WebSockets. If no, SSE or polling.
- How frequent are meaningful state changes relative to your polling interval? If the ratio is bad, move to push.
- Are you behind infrastructure that handles WebSocket upgrades cleanly? If not, SSE is less friction.
- How many concurrent connections are you projecting? Tab-per-connection SSE at scale needs a fan-out strategy.
- What happens when the stream falls behind? Pick your backpressure strategy before picking your protocol.
The protocol is almost always the easy part. The hard part is what you do with the data once it's moving.
Top comments (0)