Dev Skills

Fan-out: push vs pull

Do the work when one person writes, or when a million people read. This one choice designs the system.

1

What problem does fan-out on write solve?

One person posts. A million followers should see it. Somewhere, a million pieces of work have to happen, and you get to choose whether they happen at write time or at read time.

This trade comes up in almost every feed, timeline, chat and notification design, and the answer "it depends" is only worth points if you can say what it depends on.

2

What fan-out on write costs you

What it costs you
Push costs write amplification: one action becomes a million writes, storage for a million copies, and a backlog that delays everybody when one big account posts. Pull costs read amplification: every timeline load becomes a query across everyone you follow, merged and sorted, which is expensive and repeated constantly. The hybrid costs you two code paths for one feature, forever, plus a threshold nobody wants to own.

Every concept in here states a cost. A technique with no price is a technique you have not understood yet — and naming the cost out loud is most of what separates a senior answer from a junior one.

3

When to reach for fan-out on write, and when not to

Use it when

  • Push (fan-out on write): most users have few followers, reads massively outnumber writes, and the read must be instant.
  • Pull (fan-out on read): writes are frequent, readers are few or infrequent, or the follower counts are enormous.
  • Hybrid: a normal user base plus a handful of celebrity accounts, which describes most large social products.

Do not, when

  • Pure push when a single account can have tens of millions of followers, unless you have a special path for them.
  • Pure pull when the timeline is the main screen of the product and people open it constantly.
  • Either one without saying what happens to the biggest account on the platform.
4

How fan-out on write actually works

A
Push: fan-out on write
  • —On post, write one copy into each follower's inbox list.
  • —Reading a timeline is one sequential read of a precomputed list. Very fast.
  • —One post by a big account is millions of writes, which floods the queue.
  • —Storage grows with followers, not with posts. You store the same post many times.
  • —Deleting or editing a post means finding every copy.
B
Pull: fan-out on read
  • —On post, write once. Done.
  • —Reading means fetching recent posts from everyone you follow, then merging and sorting.
  • —Cheap writes, expensive reads, and reads happen far more often.
  • —No duplicated storage, and edits and deletes are trivial.
  • —A user following 5,000 accounts makes one very expensive query.
Which one: Push by default, because timelines are read far more than they are written. Then carve out the accounts where push breaks: above some follower count, do not fan out, and merge those in at read time. "Push for normal accounts, pull for the big ones, merged at read" is the answer the question is looking for.
The same post reaching the same followers, paid for at two different moments.

The maths is what decides it, so do the maths out loud. If the average user has 200 followers and posts twice a day, push costs 400 writes per user per day, and a timeline load costs one read. If reads outnumber writes by fifty to one, which is typical because people scroll far more than they post, push is clearly right. Now change one number: a user with 50 million followers posts. That is 50 million writes from one action, and while the queue drains it, everyone else's posts are stuck behind it.

So the design is a hybrid, and the threshold is the interesting part. Below some follower count, fan out on write into each follower's inbox. Above it, do not fan out at all. Leave the post where it is, and when a follower loads their timeline, merge their precomputed inbox with a live query for the handful of big accounts they follow. Most users follow only a few of those, so the extra query is small, and there are few enough big accounts to cache them very aggressively.

Pick the threshold from where the write cost starts to hurt the queue, measure it, and make it a configuration value rather than a constant. Ten thousand followers is a reasonable starting guess, and saying "I would tune it from queue lag" is better than any specific number.

A few details that separate an answer from a sketch. The inbox is capped: you store the most recent few hundred entries per user, not their whole history, because few people scroll that far and unbounded lists are how storage explodes. You store references, not copies: the inbox holds post ids, and the posts themselves are fetched and cached separately, so an edit or a delete happens once. Inactive users are skipped: do not fan out to someone who has not opened the app in six months; build their timeline on demand when they come back.

Ordering is the part people forget. If the timeline is strictly chronological, merging two sources is easy. The moment ranking is involved (engagement, relevance and recency combined), the merge has to score items from both sources on the same scale, which means the ranking has to be computable at read time on a few hundred candidates. That is why ranked feeds usually separate retrieval, which narrows to a few hundred, from ranking, which orders them.

The same choice appears everywhere once you see it. Chat: write once to a conversation, or copy into each member's mailbox. Notifications: generate for everyone now, or evaluate on open. A group chat with 100,000 members is the celebrity problem wearing a different hat, and the answer is the same shape.

Authorposts onceFan-outInbox 1Inbox 2Inbox 3
one write inmany writes out — reads later are free
Fan-out on write: one post is copied into every follower timeline at write time. Cheap to read, expensive when the writer has millions of followers.
Common trap
  • Choosing push or pull without doing the read-to-write arithmetic out loud.
  • No answer for the biggest account on the platform. That is the follow-up.
  • Copying whole posts into inboxes instead of references, making edits and deletes a nightmare.
  • Unbounded inbox lists, and fanning out to users who never open the app.
Say this
"Fan out on write into a capped inbox of post ids, because reads beat writes twenty to one. Above ten thousand followers I stop fanning out and merge those accounts in at read time from a heavily cached list. Cost: two code paths forever, and a threshold I tune from queue lag rather than guess."
5

The fan-out on write follow-up an interviewer will ask

"A user with 200 million followers posts. Walk me through the next 60 seconds."

What a strong answer sounds like

If I fan out on write with no special case, the next 60 seconds are an outage. Two hundred million inbox writes get queued from one action. The queue backs up, and because everyone shares it, an ordinary user's post that should appear in two seconds appears in twenty minutes. The write amplification from one account has degraded the product for everyone. So the design has to already have decided this account is different. Above a follower threshold I do not fan out at all. The post is written once, and it is put into a heavily cached "recent posts by this account" list. That is one object every one of those followers will read, which is the ideal cache shape, since it is one key with enormous read volume and it can sit at the edge. When a follower opens their timeline, I read their precomputed inbox and merge in the recent posts of the few big accounts they follow. Most people follow a handful, so that is a small extra cost paid at read time by the people who chose to follow them. The costs I would name: two code paths for one feature, permanently, and a threshold that has to be tuned from real queue lag rather than guessed. And the merge means the timeline is assembled from two sources, so ordering and pagination need care. A cursor over a merged list is harder than a cursor over one list.

6

Your turn

60-second self-check

Your product has 10 million users who each follow about 300 accounts, and people open the app 20 times a day but post once. Push or pull, and what is the number that decided it?

Stuck? Take one hint at a time0 of 3 used
0 / 25 characters
7

Learn it from the source

This page gets you interview-ready. These take you to where the idea is actually specified or measured — read them when you want the real depth.

Where you will use this