Case studies
News feed requirements and estimates
What a home feed must do, the traffic and storage numbers that shape it, and the API and data model that follow from those numbers.
A news feed shows a user recent posts from the people they follow, optionally ranked. It looks like a simple CRUD app until you multiply by hundreds of millions of users. Then the hard problem stops being storage and becomes fan-out: getting each new post to the right readers fast enough that opening the app feels instant.
Before any design, pin down the requirements and the numbers. The numbers decide the rest.
Requirements
Functional
- Create a post with text and optional media.
- Follow and unfollow another user.
- Load a home timeline of posts from followees (the accounts a user follows), newest first or ranked.
- Optional: like and repost counts on each card, which can be eventually correct.
Non-functional
- About 300M daily active users (DAU).
- A home feed p99 under 200 ms for the first page. p99 is the response time that 99% of requests beat.
- A new post appears in followers' feeds within a few seconds. Eventual consistency is fine.
- High availability on reads. A brief fan-out lag is better than a feed outage.
Out of scope unless asked: full-text search, direct messages, ad auctions, stories.
Estimates
DAU: 300M
Posts per user/day: ~0.2 -> 60M posts/day = ~700 posts/s on average (~2k at peak)
Feed loads per user: ~20/day -> 6B loads/day = ~70k loads/s on average (~200k at peak)
Average followees: ~200
Average followers: ~200 (heavy-tailed: a few accounts have 100M)Storage for post metadata is modest. At 1 KB per post, 60M posts a day is about 60 GB a day, or 22 TB a year. Media goes to object storage and a CDN, and it dominates the storage bill.
The number that matters most is the write load for fan-out. The fan-out page works through it.
API
POST /v1/posts
{ "text": "...", "mediaIds": ["m_1"] }
-> 201 { "postId": "p_987", "createdAt": "..." }
POST /v1/users/{id}/follow -> 204
DELETE /v1/users/{id}/follow -> 204
GET /v1/feed?cursor=eyJ0cyI6Li4ufQ&limit=20
-> 200 { "items": [{ "postId", "authorId", "text", "media", "stats" }], "nextCursor": "..." }Use cursor pagination with a timestamp and post ID, not offsets. An offset skips or repeats posts when new ones arrive mid-scroll, and it gets slower the deeper you page.
Data model
| Entity | Key and access | Store | Notes |
|---|---|---|---|
| User | user_id | Postgres or KV | Profile and flags such as is_celebrity |
| Post | post_id | Sharded KV or wide-column | Source of truth for content |
| Follow | (follower_id, followee_id) | Graph table, TAO-like | Needs both directions: who I follow, and my followers |
| Timeline | user_id to sorted post refs | Redis sorted set | Derived, can be rebuilt |
| Media | Object key | S3 and CDN | Uploaded with a presigned URL |
Posts are immutable content, and edits become new versions. Timelines store references (post_id and a timestamp), not full bodies. The feed hydrates the bodies from a post cache on read.
Common mistakes
- Estimating only the average. Peak here is about three times the average. Design for peak, then handle the tail as a special case.
- Using offset pagination. Posts get skipped or duplicated while users scroll.
- Storing media in the database. Keep media in object storage and serve it through a CDN.
Check yourself
-
Using the estimates, how many posts per second does the system write on average?
About 700: 60 million posts a day, divided by 86,400 seconds.
-
Why does the API use a cursor instead of an offset?
A cursor marks a specific position by timestamp and post ID, so new posts arriving mid-scroll don't shift the pages.
Key takeaways
- The numbers (DAU, posts per second, feed loads per second) shape the architecture.
- Fan-out cost, not storage, is the hard part of the design.
- Timelines hold references, and posts remain the source of truth.
- Use cursor pagination, and keep media off the database.
Further learning
Facebook's TAO paper describes the geographically distributed social graph store that sits under the follow data model.
Facebook TAO: The Power of the Graphatc13-bronson.pdfusenix.orgNext: fan-out on write and read.
Related
Case study: news feed
How a home feed copes with fan-out, celebrities, ranking and deletes at hundreds of millions of users, and where the design gets hard.
Caching
Where to put a cache, how to read and write through it, how to size it from hit-rate math, and how to keep it from serving stale data or melting down.
Object storage
Store files and media in S3-style object stores. Keep bytes out of your app servers and databases, and design uploads, metadata and costs around that split.