WebSockets vs Polling vs SSE: Cost at Scale · Formation Blog

At the protocol-framing level, WebSockets have a clear advantage over fixed-interval short polling. A WebSocket frame has 2 to 14 bytes of framing overhead under RFC 6455, depending on payload length and masking. A polling exchange carries HTTP request and response metadata and incurs a round trip even when nothing has changed. Its exact wire cost depends on the HTTP version, header compression, connection reuse, TLS, cookies, and authentication.

That is not enough to size or price a system. Per-message overhead omits the capacity consumed by idle open connections. For a large, mostly idle client population, persistent-connection capacity can make WebSockets more expensive overall, but only local measurements can establish that result.

The per-message trap

If clients exchange messages constantly, the connection setup and persistent state are amortized across substantial traffic. Chat, multiplayer games, collaborative editing, and live trading views are natural WebSocket workloads because they often require frequent, bidirectional communication.

The trade-off changes when each client receives updates infrequently. A dashboard that updates a few times an hour, a notification badge, or an order-status page that changes twice during a delivery may spend most of its life idle. A WebSocket still occupies capacity throughout that idle period.

What an idle connection costs

A WebSocket consumes state at several boundaries: the terminating process may hold a socket object, protocol and application state, and buffers; the host kernel owns the file descriptor and socket buffers; and a load balancer, proxy, or edge service may hold more state. These allocations do not all reside in the gateway process, and their size depends on the stack and workload.

Heartbeats add CPU and network work when used to detect stale connections. Measure per-connection memory and safe connection limits on the chosen stack under representative traffic, slow-client behavior, and latency thresholds. A raised file descriptor limit is a ceiling, not tested serving capacity.

A resource model, not a price result

The provisional numerical inputs show the accounting. Replace them with load tests, wire measurements, capacity limits, redundancy requirements, headroom, and unit prices from the architecture being evaluated.

Use one boundary for both alternatives: 100,000 browser clients connect through the same regional edge and load balancer. Fixed-interval short polls terminate on stateless HTTP workers; WebSockets terminate on a connection gateway. Both paths use the same authentication and downstream data source.

Hold the application contract equal across fixed-interval polling, long polling, SSE, and WebSockets. Decide whether clients need only the latest state or every event, then apply the same requirements for ordering, duplicate handling, retention, replay or catch-up, and recovery after disconnection. Neither SSE nor WebSockets supplies application-level history and recovery by itself. Include the resulting storage, routing, and recovery work in the comparison.

Suppose each client receives one update per hour and the product requires delivery within 30 seconds. A 30-second polling interval produces:

100,000 / 30 ≈ 3,333 requests per second

That rate follows from client count and the latency-driven interval, not message frequency. A 30-second interval has a worst-case detection delay near 30 seconds before network and processing, so margin may require a shorter interval. One update per client per hour is a population mean of about 28 delivered updates per second, assuming independent arrivals spread across the hour. A correlated event sent to all 100,000 clients creates a burst, so representative capacity tests must include expected fan-out correlation and burst shape. Update frequency affects payload traffic and batching, but not the fixed-interval base polling rate.

To compare the alternatives in common monetary units, define:

An hourly per-client model can then be written as:

Cpoll / N = 3600[((c0 / T + λcp + rh·ehc)Pcpu) + ((b0 / T + λdp + rh·ehb)Pbyte) + Qpoll / T + rh·Qh] + mhttpPmem + Fpoll / N

Cws / N = 3600[((ch / H + λcw + rw·ewc)Pcpu) + ((bh / H + λdw + rw·ewb)Pbyte) + rw·Qw] + mwsPmem + Qconn + Fws / N

Authentication performed on every poll belongs in c0; connection-specific authentication belongs in the relevant establishment term. Set the expressions equal only after measuring the variables. Tiered prices should be modeled piecewise rather than hidden in a fixed charge. The result is a break-even for the defined workload, service contract, and billing boundary, not an inference from unmatched figures such as network throughput and resident memory.

Capacity constraints still apply outside the equation. Polling workers must sustain the measured request rate while meeting CPU and latency thresholds. The gateway fleet must keep connection count, file descriptors, memory, heartbeat work, and slow-client buffers within tested limits. Fleet sizing must include the chosen redundancy model and headroom; standby capacity and failover behavior need representative load tests rather than a simple multiplier.

Without fixed or nonlinear terms, both totals scale with client count, leaving the variable per-client crossover unchanged. With the fixed terms, totals are affine: changing N changes Fpoll / N relative to Fws / N when fixed costs differ. Per-request and per-connection charges scale with their drivers, while tiered pricing, fleet rounding, and edge limits can change the slope or add steps. Message frequency changes delivered payload and batching: polling can return several accumulated updates in one response, while WebSockets can send each update separately or batch them. At high frequency, framing, latency, and bidirectional traffic may favor WebSockets, depending on the measured terms.

This example is specifically about fixed-interval short polling. Long polling reduces empty responses by holding a request until data arrives or a timeout expires, but retains connection and intermediary state. Reused HTTP/2 or HTTP/3 connections and header compression can reduce polling overhead while preserving transport state. Full accounting must include HTTP framing, TLS and transport overhead, relevant retransmissions, and connection state charged at the edge or load balancer.

The options can also be combined: WebSockets for an active cohort, polling for a long idle tail, or a downgrade path where quiet connections close and clients resume polling.

SSE is a one-way push option

When updates flow only from server to client, Server-Sent Events can provide a simpler semantic and browser API than WebSockets. The browser EventSource interface automatically reconnects, and the HTML standard defines how a client sends Last-Event-ID when reestablishing the stream (WHATWG HTML). That transport behavior does not provide event retention or guarantee replay. The application still owns authorization, event history, replay rules, and recovery when the requested history is no longer available.

SSE is not an escape from persistent-connection cost. It retains long-lived connections, memory, file descriptors, and intermediary state, and deployments may require proxy-buffering and timeout configuration. Its advantage is the one-way event-stream model. For occasional upstream actions, SSE can be paired with regular HTTP requests; frequent bidirectional traffic is a stronger reason to evaluate WebSockets.

The operational bill for WebSockets

If the workload justifies WebSockets, plan for what they change operationally:

Companion articles on the per-message and per-connection cost model (August 11) and persistent-connection fan-out (August 13) are forthcoming.

A concise interview answer is: “WebSockets minimize framing overhead per message, but long-lived connections continuously consume capacity, so for a large, mostly idle client population I would measure fixed-interval polling, long polling, SSE, and WebSockets against the same latency and delivery contract rather than assume push is cheaper. I would choose based on directionality, update and payload frequency, batching, service semantics, tested connection and request capacity, and measured operating cost.”