Reddit differs from other social systems in a useful way: **there is no follow graph to fan out.** Content lives in communities, and the feed is a ranked query over a community. That makes ranking and comment trees the substance of the answer.
Requirements
Functional
- Post links or text to a subreddit; browse a subreddit ranked by hot/new/top.
- Nested comment threads with unlimited depth.
- Upvote and downvote posts and comments.
- A personalised home feed merging the user's subscribed subreddits.
Non-functional
- Feeds load fast; they are the landing page.
- Vote counts can be eventually consistent and approximate.
- Extremely read-heavy, with heavy skew toward large subreddits.
50M daily users, 100K subreddits
2M posts/day, 20M comments/day ≈ 250 writes/second
Feed reads ≈ 100,000/secondRanking
No fanout means the feed is a ranked query per subreddit, precomputed and cached. The formula that made Reddit work:
score = log10(max(|ups - downs|, 1))
+ sign(ups - downs) × (seconds_since_epoch / 45000)Two properties are worth explaining, because this is the part interviewers push on:
- The logarithm means the first 10 votes move a post as much as the next 100 — early
votes matter enormously, later ones barely. Without it, a post with 10,000 votes would never be displaced.
- The linear time term means a post's score rises with submission time regardless of
votes, so newer content continuously pushes older content down. Time is added, not used as a decay divisor, which makes ranking stable and cheap: **a post's score never changes unless its votes change.**
That last property is the design win. Scores can be stored in a per-subreddit sorted set (Redis) and updated only on a vote, so serving a "hot" page is a single range read.
The "best" comment sort is a different formula — the Wilson score confidence interval — which asks "given these votes, what is the lower bound on the true approval rate". It stops a comment with 3 upvotes and 0 downvotes outranking one with 300 and 50.
Comment trees
Unlimited nesting is the modelling problem. Options:
| Approach | Read | Write | Notes |
|---|---|---|---|
| Parent pointer only | Recursive queries | Trivial | Simple, slow reads |
| Materialised path | One prefix query | Easy | path = "/12/45/98/" |
| Nested sets | Fast subtree reads | Expensive rewrites | Bad for constant inserts |
| Closure table | Fast both ways | Extra rows per edge | Storage-heavy |
Materialised path is the usual answer. Each comment stores its ancestry as a string, so
an entire subtree is one indexed prefix query, and sorting by path yields the tree already in display order.
comment_id | path | depth | score
1 | /1/ | 0 | 250
2 | /1/2/ | 1 | 90
3 | /1/2/3/ | 2 | 12
4 | /1/4/ | 1 | 45Deep threads still need pagination: load the top-level comments plus a few levels, and render "continue this thread" links that fetch a subtree on demand. A post with 50,000 comments must never be a single response.
Votes without hotspots
A viral post takes thousands of concurrent votes. Incrementing a counter column makes that row a lock hotspot.
votes user_id, thing_id, direction, created_at (the source of truth,
also prevents double voting)
counts thing_id → ups, downs (Redis, atomic INCR)
periodically reconciled from the votes tableKeep the individual vote rows — you need them to prevent double voting and to allow changing a vote — but serve the aggregate from a fast counter. Displayed counts are deliberately fuzzed and eventually consistent, which is both an anti-manipulation measure and a licence to relax consistency.
The home feed
A user subscribes to, say, 50 subreddits. The home feed is a **merge of the top N from each subscribed subreddit's cached ranking**, re-sorted by score — the k-way merge pattern, and cheap because each subreddit's ranked list is already computed. Cache the merged result per user for a short window.
Storage
posts post_id, subreddit_id, author_id, title, url/body, created_at, score
comments comment_id, post_id, author_id, path, depth, body, created_at, score
votes user_id, thing_id, direction
subs user_id, subreddit_id
rankings Redis sorted set per subreddit per sort orderShard by subreddit_id — queries are almost always scoped to one community, so this keeps
them single-shard. The risk is that a huge subreddit becomes a hot shard, mitigated by
caching its ranked pages aggressively at the edge.
Follow-ups to expect
- Vote manipulation — rate limits, account age and karma thresholds, and detecting
coordinated voting rings in the graph.
- Moderation — per-subreddit moderators, removal queues, automated rules.
- Search — a separate inverted index across posts and comments.
- Controversial sort — high engagement with a near-even up/down split.
- Editing and deleting — comments are tombstoned rather than removed, so the tree
structure below them survives.
- Live threads — a WebSocket push for fast-moving discussions.
Track this problem on the System Design sheet.
Frequently asked
How does Reddit's hot ranking algorithm work?
It adds a logarithm of the vote score to a linear function of submission time. The log means early votes matter far more than later ones, so a post with 10,000 votes cannot dominate forever; the additive time term means newer posts continuously push older ones down. Because time is added rather than used as a decay factor, a post's score only changes when its votes change — so scores can live in a sorted set and be updated on vote alone.
How do you store deeply nested comment threads?
Materialised paths. Each comment stores its full ancestry as a string like /1/2/3/, so an entire subtree is a single indexed prefix query and sorting by path returns the tree already in display order. Deep threads are paginated with 'continue this thread' links that fetch a subtree on demand rather than returning fifty thousand comments at once.
How do you handle vote counts on a viral post?
Keep individual vote rows as the source of truth — they prevent double voting and allow vote changes — but serve the aggregate from an atomic counter in Redis, reconciled periodically. Incrementing a column on the post row would make it a lock hotspot. Displayed counts being approximate and eventually consistent is acceptable, and also makes manipulation harder to measure.