Design problems
Social, feeds & contentMediumSDE-1 30 min

Design a Q&A site (Stack Overflow / Quora)

Asked at
AtlassianGoogleLinkedInMicrosoftOpenAI

The interviewer asks

“Design a Q&A platform like Stack Overflow or Quora. Users ask questions with tags, others answer, the community votes and accepts answers, and most traffic comes from people arriving through search engines.”

What a strong answer looks like

A strong answer starts from the traffic shape: very read-heavy (often > 99% reads), and most readers are anonymous visitors from Google landing on one question page. So the question page must be fast and cacheable: render it from a relational source of truth (Postgres/SQL Server is enough for the core data, as Stack Overflow famously shows), cache rendered pages and fragments, and put a CDN in front for anonymous users. Writes (questions, answers, votes, edits) are low volume but need correctness: votes are idempotent and drive a reputation ledger that unlocks privileges. Search (Elasticsearch, fed by CDC) powers site search and duplicate detection while asking; modern systems add embeddings for semantic duplicate detection. Deep dives: question-page read path and caching, votes and reputation as an append-only ledger, search and duplicate detection, and moderation. Quora-style feeds and answer ranking are a follow-up.

Concepts to mention

Read-heavy, SEO-driven trafficCDN and page/fragment cachingRead replicasPre-rendered HTMLIdempotent votes with unique (user, post)Reputation as an append-only ledgerPrivileges based on reputationChange data capture to searchBM25 plus vector search for duplicatesCommunity moderation queuesBatched view counters

1 Requirements

Functional

  • Ask a question with title, body (Markdown, code blocks) and up to 5 tags
  • Post answers and comments; edit with revision history
  • Upvote/downvote questions and answers; asker accepts one answer
  • Reputation points from votes and accepts; privileges unlocked by reputation (comment, edit, close votes)
  • Search questions by text and tags; suggest similar questions while typing a new one
  • Close, mark duplicate and delete content through community moderation

Non-functional

  • Scale: ~50M monthly visitors, ~1.5B page views/month, ~8k questions/day, ~12k answers/day
  • Question page TTFB < 100 ms for anonymous users (SEO matters), < 200 ms logged in
  • Strong consistency for reputation and votes per user (no double counting)
  • Availability 99.95%; read-only mode acceptable during DB failover
  • Search results < 300 ms; new posts searchable within ~1 minute
  • Content is permanent and public; revision history kept forever

Out of scope (say it out loud)

  • Jobs, ads and Teams (private instances)
  • Chat rooms
  • Payments for Quora-style subscriptions

2 Estimates

Page views~600/s avg, ~2,000/s peak1.5B/month ÷ (30 × 86,400) ≈ 580/s; weekday working-hour peak ~3x
Write rate< 10 writes/s for posts; ~50/s votes20k posts/day ÷ 86,400 ≈ 0.25/s; ~2M votes and edits/day ≈ 25-50/s; reads exceed writes by > 100:1
Anonymous share~80% of page viewsMost visitors come from search engines and are logged out, so CDN/page cache can serve them
Content size~500 GB total text~25M questions + ~35M answers × ~4 KB with revisions ≈ 240 GB, plus comments and history ≈ 500 GB: fits one beefy SQL server with replicas
Search index~200 GB60M posts × ~3 KB index footprint; a 3-5 node Elasticsearch cluster with replicas
Embeddings for duplicates~150 GB25M questions × 1,536 floats × 4 bytes ≈ 150 GB; quantised to int8 ≈ 40 GB

3 API

EndpointWhat it does
POST/v1/questionsAsk a question: title, body_md, tags; returns question_id and slug URL
GET/questions/{id}/{slug}Server-rendered question page with answers (SEO-friendly URL)
POST/v1/questions/{id}/answersPost an answer
POST/v1/posts/{id}/votesBody: type up|down|none; idempotent per user
POST/v1/questions/{id}/accept/{answer_id}Asker accepts an answer
GET/v1/search?q=&tags=&sort=relevance|votes|newest&page=Full-text search with tag filters
GET/v1/questions/similar?title=Duplicate suggestions while the user types a new question

4 Data model

postsPostgres / SQL Server (primary + read replicas)
post_id (PK)type (question|answer)parent_id (question for answers)owner_idtitlebody_mdbody_htmlscoreanswer_countaccepted_answer_idview_counttagscreated_atlast_activity_atclosed_reason

Questions and answers in one table (as Stack Overflow does). Indexes on (parent_id, score) for answer lists and on (last_activity_at) for 'active' lists. Store pre-rendered HTML to avoid Markdown rendering on read.

votesPostgres
(user_id, post_id) PKvote_typecreated_at

Unique key makes votes idempotent; changing vote is an update. Post score is updated in the same transaction (write rate is low enough).

reputation_eventsPostgres (append-only)
event_id (PK)user_idpost_idreason (upvote_answer +10, accept +15, ...)deltacreated_atreversed_by

A ledger: user reputation = sum of events (cached in users.reputation). Reversals add negative events instead of deleting, so audits and recalculation work.

post_revisionsPostgres
revision_id (PK)post_ideditor_idbody_mdcommentcreated_at

Full history for rollback and for showing diffs. Large but rarely read.

tagsPostgres + Redis
tag (PK)question_countwikisynonyms

Tag counts and synonyms (js → javascript) cached in Redis.

search_indexElasticsearch + vector index (pgvector or OpenSearch k-NN)
post_idtitlebody texttagsscoreanswer_countcreated_atembedding

Fed by change data capture; BM25 for keyword search plus embeddings for semantic duplicate detection.

5 Architecture

CLIENTSEDGESERVICESASYNCDATAEXTERNALGET question pageHTTPSon misspage fragmentsreads (replica), writessearch, similarrow changesembed title+bodyindex docsinvalidate cacheVisitors from GoogleLogged-in UsersCDN / Page CacheLoad BalancerWeb / API ServersSearch + SimilarServiceCDC Stream (Debezium)Indexer / EmbedWorkersPostgres Primary +ReplicasRedis (cache,counters)Elasticsearch +VectorsEmbedding Model
ClientEdge / gatewayService / workerQueue / streamCacheDatabase / storageAI / modelThird partyrequestasync (event / queue)

Hover a box to highlight its connections.

6 Request flows

Anonymous visitor opens a question from Google

  1. 1Browser requests /questions/123/how-to-reverse-a-list; CDN has a cached HTML copy for anonymous users (TTL ~60 s) and serves it in ~20 ms
  2. 2On a miss, a web server checks Redis for the rendered question page (or per-post HTML fragments)
  3. 3On a cache miss it reads the question and answers (ordered by accepted first, then score) from a read replica using the (parent_id, score) index
  4. 4It uses stored body_html (no Markdown rendering per request), renders the page, stores it in Redis and returns it with cache headers
  5. 5View count increments go to a Redis counter and are flushed to the database in batches every few minutes

Upvote an answer

  1. 1User clicks upvote; server checks privileges (reputation ≥ 15) and rate limits (votes per day)
  2. 2In one database transaction: upsert votes (user, post) → up; update posts.score += delta; insert reputation_events for the answer owner (+10); update users.reputation cache
  3. 3If the user had already upvoted, the upsert detects no change and nothing else happens (idempotent)
  4. 4Transaction commits; CDC emits the post change; a worker invalidates the page cache and updates the score in the search index
  5. 5A nightly job checks for serial voting (one user repeatedly upvoting another) and reverses those reputation events

Ask a question with duplicate suggestions

  1. 1As the user types the title, the client calls /questions/similar (debounced, ~300 ms)
  2. 2Search service runs BM25 on title + tags and a vector k-NN search on the title embedding, then merges the two lists (reciprocal rank fusion)
  3. 3The top 5 similar questions with accepted answers are shown; many users find their answer here and never post
  4. 4On submit, the question is stored, CDC sends it to indexers, and it is searchable within ~1 minute

7 Deep dives

Read path: why a cache-first monolith works

Stack Overflow is a well-known example of a top-traffic site running on a small number of web servers and a primary SQL Server with replicas. The lesson for the interview: at a few thousand page views per second and under 1 TB of data, you do not need sharding or microservices. What you need is a fast read path. Layers: (1) CDN caching of full pages for anonymous users, who are the large majority; a TTL of ~60 s is acceptable because a new answer appearing a minute late is fine. (2) Redis caches rendered page fragments per post (question block, each answer block), so a new answer only invalidates its own fragment and the answer list. (3) Read replicas take the remaining queries; writes go to the primary. (4) Store rendered HTML next to Markdown so reads never pay for Markdown parsing and syntax highlighting. (5) Counters like view_count are batched in Redis. With this, more than 95% of requests never touch the database. Logged-in users get the same cached fragments plus a small personalised part (their votes, their reputation), assembled at render time.

Votes and reputation as a ledger

Reputation is the platform's currency: it unlocks privileges (comment at 50, edit at 2,000 on Stack Overflow) so it must be correct and explainable. Model it as an append-only ledger of reputation_events, each with a reason and a link to the vote or accept that caused it. The user's reputation is the sum, cached in the users table and updated in the same transaction as the vote. Benefits: when a vote is removed, a post is deleted, or fraud is found, we add reversing events rather than editing totals, so history stays auditable and the user can see 'why my rep changed'. Rules like the daily cap (200 reputation per day from upvotes) are applied when events are generated. Because write volume is small (tens per second), a single relational transaction covering vote + score + reputation is simple and strongly consistent; no queue or saga is needed. That is a good point to make: choose the simple consistent design when the numbers allow it, and explain at what scale you would move score updates to an async pipeline.

Search and duplicate detection

Two search needs: users searching for answers, and the ask flow suggesting duplicates before a question is posted. Both are served from an Elasticsearch index fed by change data capture (Debezium reading the database log into Kafka), so the database stays the source of truth and indexing never blocks writes. Keyword search uses BM25 over title (boosted), body and tags, with filters on tags and sort by votes or recency, and code-aware tokenisation (do not split 'std::vector' or 'C#'). Duplicates are often phrased differently ('reverse a list in python' vs 'how to invert a python list order'), which keyword search misses. So we also store an embedding of each question's title and body and run approximate nearest neighbour (HNSW) search, then combine keyword and vector results with reciprocal rank fusion. A small re-ranker or rules boost questions with accepted answers. This hybrid is the same pattern as RAG retrieval and is a natural AI-era extension: an LLM can draft a summary answer from the top retrieved posts, with links, but must cite sources and never replace community answers silently.

Moderation and quality

A Q&A site lives or dies by content quality. Community moderation is privilege-based: users above thresholds can vote to close, mark as duplicate, or reopen; 5 close votes (or one moderator) close a question. Close votes are stored as rows with a review queue, and a closed duplicate links to the canonical question so search engines and users land on the best answer. Review queues (first posts, late answers, low quality) are just filtered lists of posts with flags, assigned to reviewers. Automated defences: rate limits for new users (one question per 90 minutes is a known Stack Overflow style rule), spam classifiers on new posts, link and phone number detection, and blocking of posts from users with many deleted questions. Detected voting rings trigger reputation reversal. All moderation actions are logged in a post history table so decisions can be audited and undone. AI-generated answers are a current problem; platforms set policies and use detection plus human review rather than trusting a classifier alone.

8 Trade-offs

Monolith + SQL vs microservices + NoSQL

At this scale (thousands of reads/s, tens of writes/s, < 1 TB), a well-indexed relational database with replicas and caching is simpler, cheaper and strongly consistent. Microservices and NoSQL add operational cost without solving a real problem. Say when you would change: e.g. Quora-scale personalised feeds and billions of rows of interactions.

Synchronous vote transaction vs async aggregation

With ~50 votes/s, updating score and reputation in one transaction is fine and gives exact numbers. A viral site with thousands of votes per second on one post would need async aggregation (like Reddit), accepting short lags.

Keyword vs semantic search

BM25 is cheap, explainable and great for exact error messages and code tokens. Embeddings find paraphrased duplicates but cost model calls and vector storage. Use both and fuse results.

9 Bottlenecks

Cache invalidation on hot questions

A question trending on social media gets many new answers and votes per minute, each invalidating its page. Use fragment-level invalidation and short TTLs on the full page; coalesce invalidations to at most once every few seconds.

Primary database write path

Single primary will eventually limit writes. Move high-rate, low-value writes (views, impressions) to Redis/Kafka batches first; that removes most write load before any sharding is needed.

10 Failure handling

Primary database fails

Automatic failover to a synchronous replica in seconds to a minute. During failover the site switches to read-only mode: pages still load from caches and replicas; asking and voting show a 'temporarily read-only' message.

Search cluster down

Question pages are unaffected. Site search falls back to a simple title search on the database or shows an error; the ask flow skips duplicate suggestions. CDC events wait in Kafka and are replayed when search recovers.

Spam wave

Raise rate limits for new accounts, require captcha or reputation to post links, and let high-rep users' spam flags delete posts quickly (e.g. 6 spam flags auto-delete).

11 What impresses

  • Using the numbers to argue that a single SQL primary with caching is enough
  • Designing reputation as a ledger with reversals instead of mutable totals
  • Caching full pages for anonymous users and fragments for logged-in users
  • Hybrid keyword + semantic duplicate detection with rank fusion
  • Code-aware tokenisation in search
  • Read-only mode as a graceful failover strategy

12 Mistakes

  • Jumping to microservices, sharding and Cassandra for a < 1 TB, read-heavy workload
  • Rendering Markdown on every page view
  • Storing reputation as a single mutable number with no history
  • Writing view counts to the database on every page view
  • Ignoring SEO and anonymous traffic, the biggest share of load
  • Searching with SQL LIKE '%term%'

13 Follow-ups

Q1How would you build a Quora-style personalised feed of questions to answer?
Q2How would you rank answers beyond score (recency, author expertise)?
Q3How would you add an AI-generated summary answer safely?
Q4How do you detect serial voting and sock-puppet accounts?
Q5How would you support multiple languages (Hindi, Tamil) for questions?
Q6When would you need to shard, and by what key?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free