Social media feed architecture.
Fan-out on write is the right answer until someone with ten million followers posts, and the entire design exists to handle that exception.
The components
Every row below is read from the graph that produced the diagram above, so the two cannot disagree.
| Component | Tier | Why it is there |
|---|---|---|
| Client | Client | Supporting component |
| API gateway | Edge | Supporting component |
| Post service | Application | Supporting component |
| Social graph | Application | Follower edges |
| Fan-out worker | Application | Push on write, except for celebrities |
| Feed service | Application | Merges pushed timeline with pulled hot accounts |
| Ranking | Application | Supporting component |
| Kafka | Data | Supporting component |
| Redis timelines | Data | Materialised per user |
| Cassandra | Data | Supporting component |
| Object store | Data | Supporting component |
Design decisions worth arguing about
A diagram shows what was chosen. It does not show what it cost, and that is usually the part that matters in a review or an interview.
Fan-out on write makes reads cheap and writes expensive
Pushing each post into every follower's timeline at publish time means reading a feed is a single range query, which is what you want for the operation that happens constantly. The cost is proportional to follower count, so an average user is trivial and a popular one is a million writes for a single action. That asymmetry, not the average case, is what dictates the architecture.
A pull path for the accounts that break it
Above some follower threshold, fan-out stops being viable, so those accounts are not pushed at all. The feed service instead fetches their recent posts at read time and merges. This makes reads more expensive for followers of popular accounts, which is most people, and it is still cheaper than the alternative. The complexity cost is real: two code paths producing one feed, and a threshold that needs tuning.
Timelines are a cache, not a record
Materialised timelines are derived data and should be rebuildable from posts and the graph. Treating them as authoritative means a bug corrupts something you cannot regenerate. Keeping them disposable lets you cap their length, expire inactive users entirely and rebuild on demand, which bounds memory in a way that storing every user's full timeline never could.
Ranking after retrieval, not instead of it
Ranking a candidate set you already have is fast; ranking by querying a model for every possible post is not. Retrieving chronologically and then reordering keeps the expensive part bounded. The consequence is that anything not retrieved cannot be ranked, so retrieval quality caps ranking quality, which is the same lesson as retrieval-augmented generation in different clothes.
How it changes with scale
Fan-out volume grows with the product of users and average follower count, which grows faster than either. Timeline storage grows with active users and is controlled by capping length and expiring inactive accounts. The read path is comparatively flat, which is the entire return on doing the work at write time.
Where it breaks first
A celebrity post during a spike. Even with a pull threshold, the accounts just under it produce enormous fan-out bursts that saturate the workers and delay every other user's timeline. The symptom is not an error but posts appearing minutes late for people unrelated to the event, which is why fan-out lag is a metric worth alerting on.
Draw this yourself
Open the Diagram tab and describe the system. The agent emits a semantic graph rather than coordinates, so you can edit the components and the layout re-solves instead of drifting.
When the shape is right, Implement in code turns the canvas into a markdown specification, every component, every relationship and the notes, and starts a real turn in the Code tab with it.
Questions about this design
More templates
- URL Shortener System DesignThe canonical read-heavy system: roughly a hundred reads for every write, and a redirect that has to be fast enough that nobody notices it happened.
- Chat Application System DesignLong-lived connections change everything: the hard part is not storing messages, it is knowing which of your servers is holding the socket you need to write to.
- Payment System DesignThe only system on this list where being approximately right is indistinguishable from being wrong, and where the provider, not you, holds the truth.
- RAG Pipeline ArchitectureAlmost every RAG system that disappoints is failing at retrieval, not generation, and the architecture is what decides whether you can tell.