Fan-out on write vs read
Fan-out on write vs fan-out on read
Two ways to build a home feed.
Fan-out on write (push) precomputes each follower's timeline. When an author publishes, the service copies the post into every follower's timeline, a per-user Redis list or sorted set. Reads are cheap because the feed is already assembled: read one key, take the top K. The cost lands on the write, where one publish becomes one write per follower. That is write amplification.
Fan-out on read (pull) stores the post once. At read time the feed service looks up everyone you follow and gathers their recent posts. Writes are cheap; the read is the expensive scatter-gather.
The asymmetry to remember: push write cost scales with the author's follower count, while pull read cost scales with how many accounts the reader follows. Social graphs are read-heavy, feeds read far more often than posts are written, so push is the sensible default for ordinary accounts.
Why real feeds use a hybrid
Neither pure model scales alone, so production feeds mix them per account.
- Normal authors: push (fan-out on write).
- High-follower authors: pull (fan-out on read), store once and do not fan out.
At read time the feed service does both: it reads your precomputed timeline and fetches recent posts from the few celebrities you follow, then merges and sorts so the seam is invisible.
Wrong "the hybrid pushes celebrities and pulls for everyone else." It is the reverse. You push the ordinary majority, a few hundred writes each, and pull the celebrities, whose push would be millions of writes. A reader follows only a handful of celebrities and celebrities post rarely, so the pull side stays small.
The celebrity / hot-key problem
This is the reason the hybrid exists. Under pure push, one celebrity publish turns into millions of timeline writes at once, a single logical operation hammering the write path and specific cache shards. It saturates write capacity and delays delivery of that post and every post queued behind it. Excluding high-follower authors from push removes the storm.
Where fan-out shows up
Fan-out is not only a feed concern. The same push, pull, and hybrid trade-off appears in notifications (one event, many recipients), in group chat (a message to a large group fans out to every member's inbox, and a big group is the celebrity analog), and in pub/sub or event streaming (one event delivered to many downstream consumers). Wherever one source distributes to many destinations, you choose between precomputing and assembling on demand.
The push/pull asymmetry and why read-heavy graphs pick push
Push is O(1) read and O(followers) write: the read is one range scan, the write copies the post into every follower's timeline, so cost lives on the producer and scales with follower count. Pull is O(1) write and O(followees) read: publish writes the post once, but a read scatters into a query per followed account and merges, so cost lives on the reader. Feeds are read far more often than they are written, so the read-heavy common case favors push. Storage is rarely the blocker: a precomputed timeline is a short list of post ids (roughly 200 per user in one common teaching example), so the constraint is write throughput, not bytes.
Two hot keys, two fixes
The celebrity problem is two distinct hot keys.
- Write-side hot key: a high-follower author on push turns one publish into millions of timeline writes concentrated on the same operation and shards. Fix: stop pushing that author and pull their posts at read time. Consistent hashing spreads the write load across shards.
- Read-side hot key: a viral post read by millions concentrates reads on one cache entry. Fix: replicate that entry across instances so any instance can serve it, rather than sharding a single key.
Wrong "moving celebrities to pull removes the hot key." It removes the write-side storm; a viral post is still a read-side hot key you handle with redundant caching.
Delivery and ordering
Timelines are usually a Redis sorted set: score is the publish timestamp or a monotonic id (snowflake), member is the post id, giving O(log n) insert and range reads for pagination. Timestamp ordering is fragile under clock skew across servers, so a monotonic id or a single sequencer is safer.
The fan-out job is queue-driven (for example Kafka consumer groups) and at-least-once, so a redelivery can double-insert. Timeline writes must be idempotent, which sorted-set membership on post id provides.
Redis Pub/Sub is at-most-once and fire-and-forget: a subscriber that is offline or errors loses the message with no replay, so durability needs Redis Streams. Kafka orders records only within a partition, never across; within one consumer group each partition is read by one consumer (load balancing), so delivering the same event to several independent systems needs separate consumer groups. Key by entity (user id) to keep one account's events ordered.
Where the pattern applies
The same trade-off runs through notifications, group chat (a large group is the celebrity analog), pub/sub broadcast, event streaming to multiple consumer groups, and IoT or ticker telemetry. Strict reverse-chronological order is one policy; ranked feeds relax ordering to insert relevance scoring, so exact order is often a product choice.
beta
The interviewer part is in the works.
The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.