Reddit / Quora / Stack Overflow#
Problem statement (interviewer prompt)
Design Reddit (or Quora / Stack Overflow): users post questions/threads in communities, others comment in nested threads, everyone votes. Listings (hot/new/top) must be ordered by a ranking algorithm. Support 50M+ DAU and 2B+ page views/day.
flowchart LR
U([User])
W[Write API]
POST[(Posts / Questions)]
COMM[(Comments / Answers)]
VOTE[Vote Service]
RANK[Ranking Service]
FEED[Feed / Listing API]
SRCH[Search]
U -->|post| W --> POST
U -->|comment| W --> COMM
U -->|vote| W --> VOTE
U -->|read| FEED --> RANK
RANK --> POST
POST --> SRCH
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class U client;
class W,VOTE,RANK,FEED,SRCH service;
class POST,COMM datastore;
flowchart TB
subgraph Clients
Web
Mobile
API
end
subgraph Edge
CDN
LB
GW[API Gateway]
end
subgraph Write
POST[Post / Question Service]
COM[Comment / Answer Service]
VOTE[Vote Service]
EDIT[Edit history / versioning]
FLAG[Flag / Report]
end
subgraph Stores
PDB[(Posts Postgres / Cassandra<br/>sharded by subreddit / topic)]
CDB[(Comments tree per post)]
VDB[(Votes - Redis counters)]
USER[(Users)]
META[(Communities / Tags)]
HIST[(Edit history)]
SEARCH[(Elasticsearch)]
end
subgraph Read
LIST[Listings: hot / new / top]
THREAD[Thread / Question view]
USERFEED[Home feed]
NOTIF[[Notifications / Inbox]]
end
subgraph Ranking[Ranking Algorithms]
HOT[Hot - Reddit log decay]
BEST[Best - Wilson confidence]
CON[Controversial]
TOP[Top in window]
SOFT[SO score - score + age decay]
QPER[Quora personalized DNN]
end
subgraph Async
K[[Kafka]]
SC[Score recomputer]
SPAM([Spam classifier])
BAD[Bad actor detector]
EMB([Embeddings job])
REC([Recommendations])
end
subgraph Cache
R1[(Hot post cache)]
R2[(Vote count cache)]
R3[(Comment tree cache)]
end
Clients --> CDN --> LB --> GW
GW --> POST --> PDB
GW --> COM --> CDB
GW --> VOTE --> VDB
POST --> K
COM --> K
VOTE --> K
K --> SC --> R2
K --> SPAM
K --> BAD
K --> EMB --> REC
POST --> SEARCH
GW --> LIST --> R1
R1 -. miss .-> PDB
LIST --> Ranking
GW --> THREAD --> R3
R3 -. miss .-> CDB
GW --> USERFEED --> REC
GW --> SRCH[Search] --> SEARCH
Ranking --> SC
FLAG --> SPAM
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class GW edge;
class POST,COM,VOTE,EDIT,FLAG,LIST,THREAD,USERFEED,HOT,BEST,CON,TOP,SOFT,QPER,SC,BAD,SRCH service;
class PDB,CDB,USER,META,HIST,SEARCH,R1,R2,R3 datastore;
class VDB cache;
class NOTIF,K queue;
class SPAM,EMB,REC compute;
Ranking formulas#
- Reddit Hot:
score = log10(max(|ups - downs|, 1)) + sign × seconds_since_epoch / 45000. - Reddit Best: Wilson lower-bound of upvote ratio for comment ranking.
- Stack Overflow:
(upvotes - downvotes) + acceptance + age decay. - Quora: personalized DNN over content + viewer features.
Comment tree#
- Stored materialized-path or adjacency list with path encoded.
- Paginated with "load more replies" to avoid huge trees.
- Vote counts cached separately to allow O(1) update.
Subreddit / community#
- Sharded by
subreddit_id- locality benefit (listings & posts together). - Hot listings per community precomputed every few seconds.
Search#
- Elasticsearch index per content type (posts, comments).
- Real-time CDC from Postgres binlog.
Spam / abuse#
- ML classifier on submit + behavioral signals (vote ring detection).
- Shadow-ban + report queues.
Glossary & fundamentals#
Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.
| Tag | Concept | What it is | Page |
|---|---|---|---|
HLD |
CDN | edge caching for static assets | cdn |
HLD |
API gateway / BFF | single ingress, auth, rate limit, routing | api-gateway |
HLD |
Sharding | horizontal partitioning across nodes | database-sharding |
HLD |
Pub/Sub & message brokers | topics, consumer groups, delivery semantics | pub-sub-pattern |
HLD |
Leader/follower replication | sync/semi-sync/async replication, failover | replication-leader-follower |
HLD |
Change Data Capture | WAL/binlog tailing, outbox publishing | change-data-capture |
Quick reference#
Functional#
- Post / question with title, body, tags, media.
- Threaded comments / answers (deeply nested).
- Voting (up/down or accept).
- Listings: hot, new, top, controversial.
- Per-user feed, notifications, mentions.
- Moderation (community + global).
Non-functional#
- Read-heavy 50:1; comment voting bursts.
- p99 listing < 200 ms.
- Eventual consistency on vote counts OK; user must see own vote immediately.
Capacity (Reddit-scale)#
- 50M+ DAU, 1B+ posts/comments total.
- ~2B page views/day → ~25k/s avg.
- Storage: text ~2 KB avg × 1B posts = 2 TB + comments many TB.
Schema highlights#
posts(id PK, subreddit_id, author, ts, title, body, score, num_comments)comments(id, post_id, parent_id, path, author, body, score)materialized pathvotes(user_id, target_id, value, ts)Cassandra; counters in Redissubreddits(id, name, type, rules)
Trade-offs#
- Materialized-path comments simplify thread queries; cost: rewrite path on move.
- Eventually consistent vote counters allow huge scale; show user-personal vote from local cache.
- Personalized vs algorithm-only: SO uses simple formulas (signals trust); Quora goes full ML.
- Sharding by subreddit localizes hot subs but can hotspot one shard.
Refs#
- Reddit "Hot" ranking blog post (Amir Salihefendic).
- Quora engineering posts (Webnode, Quora Search).
- Stack Overflow architecture (Nick Craver's blog series).
- ByteByteGo "Design Reddit".
FAQ#
How are nested comment threads modeled?#
Each comment stores parent_id and a precomputed path or depth. Queries fetch all comments for a post, then the client tree builds the thread by walking parent links.
How is the Reddit Hot ranking computed?#
Hot combines log-scaled score with a time-decay term: log(votes) plus age-in-seconds divided by a constant. Older posts with high scores still float above brand-new ones.
How do you count votes for a hot post?#
Aggregate vote events into per-post counters via a streaming pipeline. A short-window in-memory counter handles bursts, and periodic flushes update the canonical store.
How does subreddit isolation work?#
Each subreddit is a logical partition keyed by name. Listings and search are filtered by subreddit ID, and per-subreddit moderation rules apply at write and read time.
How does Reddit handle 2B page views per day?#
Read-through caches like Redis or Memcached serve hot post listings, CDNs front anonymous traffic, and the write path goes through a queue to absorb voting bursts.