InterviewKata
System design · Worked design D29 of 46 · Social and content · Long form

Design a question-and-answer site

People ask questions, others answer, everyone votes, and the best answer should rise to the top, for the person who asked and for the millions who arrive from a search engine years later. Most traffic is anonymous reading; the hard parts are ranking answers fairly, spotting duplicate questions, and keeping a community of writers motivated.

1. The prompt

"Design a Q&A site: users post questions, write answers, vote, and follow topics. Show the best answers first, and help people find existing answers before they ask again."

What makes it hard:

2. Frame the problem

How big?

300 M monthly visitors, most of them signed out; 50 M questions with 150 M answers stored.

Signed-out readers of old questions mean pages can be cached at the CDN.

How many writes?

~100 K new questions, ~300 K answers and ~5 M votes a day.

Votes are the only frequent write; they need cheap counters, not row locks on hot answers.

Is there a personalised home feed?

Yes: questions from followed topics and people, ranked.

A feed pipeline (Design D06), but questions are long-lived, so ranking matters more than recency.

Rich content?

Markdown text with images and code blocks.

Images go to blob storage; text is small and stored in the database.

Should we stop duplicate questions?

Suggest similar questions while typing, and let the community merge duplicates.

A similarity search at question time, plus a merge workflow.

Reputation and moderation?

Points from votes unlock abilities (editing, closing); spam and abuse must be handled.

Votes feed reputation, so vote fraud matters; moderation needs queues and tools.

Search?

Full-text search across questions and answers.

A search index fed from the database (Design D26, Module 12).

3. What it must do

  1. A user can ask a question and is shown similar existing questions before posting.
  2. A user can answer and vote; each question shows its answers best first.
  3. A user sees a feed of questions from topics and people they follow, and can search everything.

Not now: private messaging, paid answers, live sessions, AI-written answers (a follow-up in section 10).

4. How well it must do it

TargetWhy this number
Question pages: p95 under 300 ms, even for signed-out visitors worldwide speed · where it runsMost visitors arrive from search; slow pages lose them and their search ranking.
Fair ranking: a good answer with few votes isn't buried under an older one; vote counts update within seconds data qualityWriters stay only if good work is seen.
Duplicate suggestions appear as the asker types (under 300 ms) speedEvery duplicate prevented is one more question with a complete answer.
Votes are counted once per user per post, and fraud doesn't move reputation consistency · securityReputation unlocks moderation powers.
Reads keep working if writes are degraded surviving failuresReading is 99% of the value.

5. Numbers that change the design

QuantityWorking→ so we…
Page views~1 B a month ≈ 400 a second on average, a few thousand at peakModest for cached pages → so signed-out question pages come from the CDN and a page cache
Votes5 M a day ≈ 60 a second, bursts on viral answers→ so one row per (user, post) for uniqueness, plus a counter updated asynchronously
Stored text200 M posts × ~2 KB ≈ 400 GBFits one database cluster → so we start with one relational primary and read replicas; no sharding on day one
Reality checkStack Overflow served ~66 M page loads a day in 2016 from 9 web servers and 4 SQL servers in 2 clusters→ so caching and a well-indexed database go a very long way

6. The nouns

questions   question_id, author_id, title, body, topic_ids[], score, answer_count, accepted_answer_id, duplicate_of, created_at
answers     answer_id, question_id (index), author_id, body, up, down, rank_score, created_at
votes       user_id, post_id, value (+1 | -1), created_at     PRIMARY KEY (user_id, post_id)
follows     user_id, target_type (topic | user), target_id
reputation  user_id, points                                    (derived from votes, recomputable)

7. The contract

POST /v1/questions             {title, body, topics}   Idempotency-Key: …   → {question_id, url}
GET  /v1/questions/similar?title=…                     → [{question_id, title, answer_count}]   (while typing)
GET  /v1/questions/{id}?answers_sort=best&cursor=…   → {question, answers: [...], next_cursor}
POST /v1/questions/{id}/answers {body}                 → {answer_id}
PUT  /v1/posts/{id}/vote       {value: 1 | -1 | 0}     → {up, down}       (PUT: repeating it is harmless)
GET  /v1/feed?cursor=…                                 → [{question summary}]
GET  /v1/search?q=…&cursor=…                          → [{question summary, matched answer snippet}]

8. First working version

Stateless web servers, one relational database with replicas, Redis for caching, a CDN, and blob storage for images.

8.1 Asking (with duplicate suggestions)

As the title is typed, the client asks for similar questions (first version: full-text search on titles). On submit, one insert, then an event so search, feeds and notifications update asynchronously.

8.2 Reading a question

A signed-out visitor gets the whole rendered page from the CDN or the page cache. Signed-in users get the same cached page plus a small personal layer (their votes, follow state) fetched separately.

8.3 Voting

Upsert the vote row keyed by (user, post): repeating a vote changes nothing, and switching from up to down is a single update. Counts on the answer are updated from that change.

Parked for laterranking answers fairly (9.1) · real duplicate detection (9.2) · hot answers' counters (9.3) · the personalised feed (9.4) · keeping caches fresh after edits and votes (9.5) · spam and vote fraud (9.6).

9. Make it hold up

9.1 Ranking answers fairly fair ranking

ApproachWhy
✗ BadNet votes (up − down)The oldest answer has had the most time to collect votes; a better new one never catches up.
~ GoodShare of upvotes (up ÷ total)Fixes age, but one upvote out of one beats 95 out of 100.
✓ GreatThe lower bound of a confidence interval on the share of upvotes (the Wilson score), plus a quality model (length, code, author's track record) and a small boost for the accepted answerAnswers with few votes are ranked cautiously, not punished or over-promoted. Try it in section 13.

Compute rank_score when votes change (asynchronously) and store it, so reading a question is a simple indexed sort.

9.2 Finding duplicate questions suggestions under 300 ms

9.3 Votes on a hot answer votes counted once

9.4 The personalised feed reads keep working

Unlike a social feed, questions stay relevant for years and topics have millions of followers, so fan-out on write is wasteful. Build the feed on read: take recent and top questions from the user's followed topics (each topic's list precomputed and cached), merge, rank by a model (topic affinity, answer quality, freshness), and cache the result for a few minutes. Design D06 explains the push vs pull trade-off.

9.5 Caching pages that change question pages under 300 ms

ApproachWhy
✗ BadNo page cache: render every view from the databaseWorks, but every read becomes several queries; spikes from search engines hit the database.
~ GoodCache rendered pages with a long TTLFast, but a new answer or edit stays invisible for the TTL.
✓ GreatCache signed-out pages at the CDN with a short TTL (a minute) plus stale-while-revalidate, purge or bump a version on edits and new answers, and keep vote counts slightly stale on purposeAlmost every read is a cache hit; content changes show within a minute; counts don't need to be exact.

9.6 Spam, abuse and vote fraud security

New posts from new accounts go through a spam classifier and rate limits; low-confidence posts wait in a review queue. Vote fraud (sock-puppet accounts, voting rings) is detected offline by looking for accounts that vote mostly for one person, then those votes are reversed and reputation recomputed. Users unlock moderation abilities as reputation grows, which spreads the review work.

9.7 The whole design after the deep dives

10. Interviewer follow-ups

Show an AI-generated answer at the top.

Generate it with retrieval over the site's own answers (Module 29), label it clearly, cite the answers it used, and rank human answers by their own scores. Cache it per question; regenerate when answers change. Watch quality and the incentive for humans to keep writing.

A question goes viral from a news story.

The CDN absorbs the reads. Votes and answers burst on one question: batching keeps counter writes small, and rate limits slow sudden waves of new accounts.

The database outgrows one primary.

Move votes and counters to their own store first (they're the hottest writes), then shard questions and answers by question ID so a page is always one shard. Search and feeds already read from derived stores.

Support many languages.

Separate sites or language partitions, a language-aware search analyser and embeddings per language, and duplicate detection within each language.

Notify people when their question gets an answer.

The answer event feeds a notification service (Design D05) with batching, so a question receiving 20 answers sends one digest.

Delete a user's account and content.

Remove personal data; keep or anonymise their posts according to policy, since others' answers and votes depend on them. Purge caches and the search index, and recompute affected reputation.

Search engines crawl aggressively.

Serve them the cached pages, publish sitemaps, and rate-limit unknown crawlers at the edge.

11. When things break

FailureWhat users seeHow we detect itWhat limits the damage
Primary database downCan't post or vote; reading worksWrite errorsFailover to a standby; pages served from caches and replicas
Counter worker laggingVote counts a little behindQueue lagCounts are derived; catch up from the queue
Search index staleNew questions missing from searchIndex lagRe-feed from the change stream
Embedding service downFewer duplicate suggestionsError rateFall back to keyword suggestions
Spam waveJunk questionsSpam score spikes, new-account rateStricter rate limits and review queue for new accounts
Bad cache purgeOld answer shownEdit-to-visible delayShort TTLs as a backstop

12. Wrap-up and the clock

Trade-offs we made:

What we'd watch: CDN and page-cache hit rates · question page p95 · duplicate-suggestion click-through · vote queue lag · spam rate · answers per question.

At 10×: separate the vote store, shard questions by ID, more CDN capacity.

A 60-minute interview

0–5Frame: readers vs writers, votes, duplicates
5–10Must do, how well, numbers
10–15Nouns, contract
15–25First version: ask, read, vote
25–50Deep dives: ranking (9.1), duplicates (9.2), caching (9.5)
50–60Votes or feed, follow-ups, wrap-up

A 90-minute interview

0–8Frame, including moderation and SEO
8–15Must do, how well, numbers
15–22Nouns, contract
22–35First working version
35–75Deep dives 9.1–9.6 and the final picture
75–85Follow-ups: AI answers, scaling the database
85–90Trade-offs, metrics, 10×
LevelWhat a strong answer shows
Mid-levelA relational model with a unique vote key, CDN and Redis caching, full-text search, a simple ranking with its flaw explained.
SeniorConfidence-based ranking, embeddings for duplicates, asynchronous counters, feeds on read with reasons, cache freshness strategy.
Staff+Community incentives and abuse as design inputs, recomputable derived data (reputation, counts), SEO and duplicates merged into canonical pages, evaluation of ranking and suggestion quality.

Common mistakes:

13. Try it, check yourself, read more

Answer-ranking lab. Five answers to one question, with their upvotes and downvotes. Switch the ranking and watch the order change. Then give the newest answer a few more upvotes.

4

    Wilson lower bound at 95% confidence: the lowest share of upvotes that's still consistent with the votes seen so far.

    Which score ranks a 3-up/0-down answer fairly against a 90-up/10-down one?

    With 3 votes we're unsure, so the lower bound is modest; with 100 votes it's close to 90%.

    What guarantees one vote per user per answer?

    The database enforces it; counters are derived from the votes.

    How do you catch duplicates worded differently?

    Meaning-based vectors catch paraphrases that share no words.

    Topics have millions of followers and questions stay relevant for years. How is the feed built?

    Pushing each question to millions of followers wastes work most will never read.
    ResourceWhy
    How not to sort by average rating (Evan Miller)Why the Wilson lower bound beats net votes and ratios.
    Stack Overflow: the architecture, 2016 edition (Nick Craver)A huge Q&A site on a handful of servers, thanks to caching.
    Quora Question Pairs (Kaggle)The duplicate-question problem as a public dataset.
    MinHashFast near-duplicate detection on text, before or alongside embeddings.
    Binomial proportion confidence intervalThe maths behind the Wilson score.