← QuickNotix blog

Real-Time Delivery · Architecture deep dive

Low-Latency Push Notifications: Scaling WebSockets for Million-User Apps

WebSocket infrastructure fails in stages. It works fine at ten thousand connections, strains at a hundred thousand, and collapses at a million — usually not from raw throughput but from fan-out amplification, reconnect storms, and unbounded per-connection buffers. Each of those has a specific structural fix.

Separate the connection tier from the delivery tier

Connection gateways should do one thing: hold sockets, authenticate, and forward. Business logic belongs behind them, consuming from the event backbone. This separation lets you scale gateways on connection count and delivery services on message volume, which are entirely different curves.

Gateways must be stateless with respect to application data. Any per-user state they need — subscriptions, presence, delivery cursors — belongs in a shared store so a client can reconnect to a different gateway and resume without a rebuild.

Route by subscription, never by broadcast

The amplification trap is delivering every event to every gateway and filtering at the edge. At a million connections this saturates the internal network long before it saturates the client links. Instead, maintain a subscription index mapping topic to the gateways holding interested connections, and route only to those.

For genuinely broad fan-out — a global announcement — invert the pattern: publish once to a shared channel each gateway consumes, and let each expand locally to its own connections. Choosing per-topic between targeted routing and local expansion keeps both cases efficient.

Apply backpressure per connection

A slow client must never grow an unbounded server-side buffer, because one such client multiplied across a bad network region exhausts gateway memory. Cap the per-connection outbound queue, and on overflow choose a policy explicitly: drop intermediate updates for state-style messages, coalesce to the latest value, or disconnect and let the client resynchronize.

Coalescing is often the highest-value optimization. Clients rendering live state rarely need every intermediate value — only the latest one, delivered promptly.

Survive reconnect storms

When a gateway dies, its connections reconnect simultaneously, and naive clients retry immediately and in lockstep. Require exponential backoff with jitter in the client, enforce connection rate limits at the edge, and keep enough gateway headroom that losing one node does not overload the survivors.

Give clients a resume token so reconnection replays only what was missed. Without it, every reconnect triggers a full state fetch, and the reconnect storm becomes a database storm.

Work with QuickNotix

QuickNotix designs event-driven architecture and real-time messaging systems — Kafka pipelines, pub/sub fabrics, and reactive backends built to stream, scale, and stay observable.

Request a pipeline audit