CMD Guide
HomeSystem DesignDistributed File System

Push vs Pull Notification Systems

Push vs Pull: Who Initiates the Transfer?

Every notification system reduces to one design decision: does the server initiate the transfer the moment new data exists (push), or does the client initiate it by asking (pull)? Everything else — latency, server cost, complexity, battery life — falls out of that one choice.

Push: server-initiated delivery

Pull: client-initiated retrieval

diagram
diagram

Side-by-Side Comparison

DimensionPushPull
InitiationServer-initiatedClient-initiated
TimelinessNear-instant, bounded by network transitBounded by poll interval; can lag by up to one full interval
Server stateMust track how to reach each client (connection, token, webhook URL)Stateless per request; server answers whatever asks
Wasted workNone if delivery is targeted correctlyMost polls find nothing new when the update rate is low relative to poll frequency
Client costHolds a channel open, or must be reachable (battery/network implications on mobile)Only active while polling; can poll on its own schedule
Implementation complexityHigher — connection management, retry/backoff, delivery guaranteesLower — standard request/response

Choosing a Transport for Server-to-Client Push

"Push" is a goal, not a protocol. In practice you pick from five concrete transports, each trading latency, connection cost, and complexity differently.

TransportWho opens the connectionDirectionReconnect handlingServer cost at scale
Short pollClient, on a fixed timerClient to server to clientTrivial — it is just the next scheduled requestHigh: request rate is constant regardless of whether data changed
Long pollClient, but the server holds the request open until data arrives or a timeout firesClient to server to clientClient must reconnect after every response, including empty timeoutsMedium-high: one held connection per client plus steady reconnect churn
Server-Sent Events (SSE)Client opens onceServer to client onlyBuilt into the browser (EventSource), including resuming from Last-Event-IDMedium: one long-lived HTTP connection per client, server pushes text frames
WebSocketClient opens once, upgraded from HTTPFull duplex: server and client both waysManual — you write your own heartbeat and reconnect logicMedium-high: one full-duplex socket and its state held per client
WebhookServer (the sender) opens a connection to a URL the receiver registeredSender to receiver; receiver exposes an HTTP endpointSender's responsibility: retries with backoff on failureLow for the receiver: no idle connections at all between events

Decision rules

Traced Example: How Wasteful Is Long Polling, Really?

Take a long-poll notification endpoint serving 1,000,000 concurrently connected users. Each user's messages arrive as a Poisson process averaging λ = 1 message per minute (≈ 1/60 per second). The server holds each request open for up to T = 30 seconds: if a message arrives first, it is returned immediately; if not, the connection times out with an empty body and the client reconnects right away.

Step 1 — probability a message beats the timeout

Because Poisson inter-arrival times are exponentially distributed, the probability that no message arrives before the timeout is:

P(timeout) = e^(-λT) = e^(-(1/60)·30) = e^(-0.5) ≈ 0.607

So about 60.7% of long-poll cycles end via the timeout with nothing to deliver, and only the remaining ≈39.3% end because a real message arrived. This is the opposite of "nearly every response carries data": for a chatty-enough poll interval relative to a sparse one-message-per-minute user, most round trips are empty.

Step 2 — expected cycle length

The expected time until a cycle ends (by message or timeout, whichever comes first) is:

E[min(Exp(λ), T)] = (1/λ)·(1 - e^(-λT)) = 60 · 0.393 ≈ 23.6 seconds

Step 3 — reconnect rate across all users

Each user reconnects roughly once every 23.6 seconds, so one user contributes ≈ 1/23.6 ≈ 0.0424 reconnects per second. Across 1,000,000 users:

1,000,000 / 23.6 ≈ 42,000 reconnects/second

Step 4 — how many of those reconnects actually carry a message

Only the ≈39.3% of cycles that end via a real message deliver data:

42,000 × 0.393 ≈ 16,500-16,700 message-carrying responses/second

That matches a sanity check: total message production across all users is 1,000,000 users × 1/60 msg/s ≈ 16,700 msg/s, and every message is delivered exactly once, so the message-carrying reconnect rate has to match the production rate — and it does.

What this means

The remaining ≈25,300-25,500 reconnects per second (roughly 60-61% of all reconnects) are pure overhead: a full HTTP round trip, and in many stacks a fresh TCP/TLS handshake, for zero bytes of payload. That overhead is the real cost of long polling at this traffic mix, and it is why the transport table above rates long poll as "medium-high" server cost — the number is driven by the timeout path, not the message-delivery path.

diagram
diagram

A Related Push/Pull Choice: Fan-out-on-Write vs Fan-out-on-Read

Social feeds face their own push-vs-pull decision, independent of transport: when a user posts, do you push the post into every follower's precomputed feed immediately (fan-out-on-write), or leave feeds unmaterialized and assemble them by merging each followee's timeline at request time (fan-out-on-read)?

When to use which

Use fan-out-on-write as the default: most accounts have a follower count small enough that paying the write cost per post is cheap, and it keeps reads fast for the common case, since users check their feed far more often than they post. Switch to fan-out-on-read — or better, a hybrid — for celebrity accounts with millions of followers: fanning out a single post from an account with 50 million followers to 50 million inboxes on every post would be a write storm that dwarfs normal traffic. The well-documented approach at Twitter-scale systems is exactly this hybrid: fan out on write for ordinary accounts, and for accounts above a follower-count threshold, leave their posts unmaterialized and merge them into a follower's feed at read time instead.

Hybrid feed cache: Redis ZSETs and celebrity read-time merge

A practical hybrid feed keeps ordinary users on fan-out-on-write but treats high-follower accounts as read-time merge inputs. The common cache layout is a Redis Sorted Set (ZSET): home:{user_id} maps post IDs to scores such as post timestamp or ranking score. Ordinary followee posts are pushed into each follower's home ZSET with ZADD, and old entries are trimmed with ZREMRANGEBYRANK or TTL policy. Celebrity posts live in per-author ZSETs such as author:{celebrity_id}:posts and are not copied to millions of followers on write.

The read path is then explicit: (1) fetch the follower's precomputed home:{user_id} ZSET, (2) fetch the recent ZSET slices for the celebrity accounts that user follows, (3) merge by score in memory or with a Redis sorted-set union/intersection pattern, (4) de-duplicate post IDs, apply ranking/visibility filters, and return the top N. No database hit is needed on the hot read path if both the precomputed feed and celebrity recent-post caches are warm.

The celebrity threshold should use active follower state, not just total follower count. An account with 10M historical followers but 20k daily active readers may be cheaper to fan out than an account with 2M highly active followers. Track active followers over the feed freshness window, post frequency, and write amplification budget; promote/demote accounts across the threshold slowly to avoid cache churn.

Operationally, the signals worth alerting on fall straight out of the choices above: the empty-timeout ratio and reconnect rate on any long-poll tier (a rising empty ratio means the poll window is too short for the message rate), live WebSocket/SSE connection counts against process memory (each held channel is retained state), and fan-out write amplification per high-follower author (the number that decides threshold promotion). Feed p99 latency spikes when the celebrity read-merge path degrades or a hot ZSET falls out of cache, and mobile battery/complaint tickets track aggressive short-poll intervals more than any other client behavior.

Sources

Transport characteristics drawn from the WHATWG HTML Living Standard's Server-Sent Events (EventSource) section, RFC 6455 (The WebSocket Protocol), and RFC 7230/7231 (HTTP/1.1 semantics) for long-poll and short-poll request-response behavior. The reconnect-rate derivation uses the memoryless property of the exponential distribution (Poisson process inter-arrival times), a standard queueing-theory result — see Kleinrock, Queueing Systems, Volume 1: Theory. The fan-out-on-write/fan-out-on-read hybrid pattern follows publicly described large-scale social-timeline architectures (a fan-out service materializing home timelines for most accounts, with read-time merging reserved for very high-follower accounts).

Drill ladder: transport pick & hybrid threshold

  1. L1: Derive the long-poll empty-timeout ratio for λ=1 msg/min, T=30 s (formula: e^(−λT)); check your answer against Step 1 of the traced example above.
  2. L2: For 1M users, compute the reconnect rate and the fraction of it that is pure overhead; check against Steps 3–4 above.
  3. L3: When SSE beats WebSocket (server→client only).
  4. L4: Celebrity threshold by active followers not total — why.
  5. L5: Redis ZSET home merge steps on read.
🤖 Don't fully get this? Learn it with Claude

Stuck on Push vs Pull Notification Systems? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Push vs Pull Notification Systems** (System Design) and want to truly understand it. Explain Push vs Pull Notification Systems from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Push vs Pull Notification Systems** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Push vs Pull Notification Systems** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Push vs Pull Notification Systems** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes