Design the Reddit Homepage
You're asked to design a ranked community feed like the Reddit homepage. It draws posts from the communities a user subscribes to, serves tens of millions of daily users, and reflects new posts and votes within roughly a minute. Unlike a chronological feed, it ranks posts using both score and recency.
Instagram's feed asks what the accounts you follow have posted. Reddit's homepage has to decide which posts across all your communities are worth showing now. That order keeps changing as votes arrive and posts age, even when nobody publishes anything new.
Clarify the requirements
- Is the feed personalized or global? A single global "hot" list is much simpler than a homepage built from each user's subscriptions. Ask which version you need to design because the answer changes the whole architecture.
- What drives ranking? Score and age at minimum. Personalization, per-community weighting, and spam signals are all common additions.
- How fresh must the ranking be? Ask whether changes need to appear within seconds or minutes. Allowing a minute or two of lag gives you room to batch the ranking work.
- Do we need to handle vote fraud? This is often out of scope, but you should confirm it.
Assume that each user gets a homepage assembled from their subscribed communities. A score-and-time function ranks the posts, and the result may lag by about a minute.
Back-of-envelope numbers
- Reads:
- Votes: , spiking far higher on viral posts
- ~100k active communities, of which only a few thousand are busy at any moment
There are far fewer communities than users. That difference lets you precompute one ranked list per community and assemble each user's homepage from those shared lists instead of ranking posts separately for every user.
High-level architecture
- Vote service. Records the vote durably and idempotently, one vote per user per post.
- Vote stream. Decouples voting from ranking so a vote never waits on a recompute.
- Ranking job. Recomputes the top posts for each active community on a short interval.
- Hot list. Keeps a small, ordered list of post IDs for each community in memory.
- Homepage service. Merges hot lists for the user's subscriptions and returns a page.
- Subscriptions. Which communities each user follows.
- Post cache. Hydrates post IDs into titles, thumbnails, and current counts.
Deep dive 1: the ranking function, and why it's time-decayed
Sorting only by score would leave the same all-time favorites at the top forever. Combine score with age so older posts gradually fall and new posts have a chance to rise.
The classic shape looks like:
rank = log10(max(|upvotes - downvotes|, 1)) + (sign × seconds_since_epoch / 45000)
The exact formula matters less than two of its properties. The logarithm gives the first ten upvotes more weight than the ten-thousandth, which helps new posts climb. Age is an additive term measured against a fixed epoch. Because time affects every post equally, you only need to recompute a post's score when its votes change; relative order stays intact without rescoring everything.
That second property makes precomputation practical. If the system had to rescore every post every minute, the rest of this design would fall apart.
Deep dive 2: precompute per community, merge per user
Ranking every post a user could see at request time is too expensive. A user subscribed to 50 communities would trigger 50 queries and a merge across hundreds of thousands of posts on every page load.
Instead, precompute per community because every subscriber shares the same community list. A ranking job maintains the top few hundred posts for each community. A homepage request fetches the lists for the user's subscriptions, merges them by score, and returns one page. Merging 50 presorted lists of 300 entries takes only milliseconds.
This applies the fan-out idea from Design Instagram one level higher. Precompute the data users share, then keep the per-user work to a cheap merge.
Deep dive 3: how often to recompute
The ranking job does not need to touch every community. Most receive only a handful of votes per hour, so their ordering stays stable for long stretches.
- Recompute active communities frequently. A community receiving votes in the last minute gets recomputed on a short cycle. Everything else can wait.
- Recompute cheaply. You only need to re-score posts whose votes changed, then re-sort a limited candidate set of the top few thousand posts by recency, rather than the community's entire history.
- Let the front page lag. With a freshness budget of about a minute, you can batch votes and recompute on an interval instead of reacting to every vote. This saves substantial work, which is why you should ask about freshness up front.
Deep dive 4: hot posts, vote spikes, and paging
A viral post can send every vote to the same row and create heavy contention. Use sharded counters, then aggregate them on the same interval as the ranking job because the ranking may already lag.
Vote fraud still needs a boundary even if it is out of scope. Enforce one vote per user per post with a unique constraint on (user_id, post_id) rather than storing votes as bare increments.
Paging needs special care because the list can reorder between requests. Offset pagination may show duplicate posts or skip some entirely. Use a cursor containing the score and post ID of the last item seen, so the next page continues from a stable position even if the rankings have shifted.
Common pitfalls
- Ranking at read time. Impossible at scale, and it puts the most expensive work on the hottest path.
- Precomputing per user. Multiplies work by your user count when the shared unit is the community.
- Score without time decay. The homepage freezes on all-time favorites and never turns over.
- Offset paging over a reordering list. Users see duplicates and miss posts.
- Not asking about freshness. Without a stated budget you'll design for real-time ranking you don't need.
Leveling signals
Related lessons
Build a photo feed that assembles each user's timeline from the accounts they follow.
Assemble a product page from inventory, pricing, reviews, and recommendations.