Company questionsGroundworkPhonePe

System design · Feeds and ranking

Design a Quora-style Q&A platform

  • Reported in several places
  • SDE-2
  • 2 diagrams
  • 2 sources

Two or more independent public pages, at least one a candidate write-up.

The prompt
Design a question-and-answer site where users post questions, write answers, upvote, follow topics and people, and search for existing questions. Assume 50 million daily users, mostly reading, and pages that should load in under 300 ms.

A representative prompt in the style reported, not a quote from PhonePe. The answer below is written for this site.

Try it first.The answer is covered until you pick. Talk it through against a 45 minute clock, or just read it.

Ask first

Clarify the problem before you draw anything.

Questions first: what are the core objects (question, answer, comment, topic, user)? Is there a personalized home feed, or only topic pages and search? How should answers be ordered on a question page: votes, recency, author reputation? Do we need anonymous answers, edits and deletion, and moderation? How important is finding duplicate questions?

Assumed scope: post a question with topics, write answers, upvote and downvote, follow topics and users, a personalized feed, search by text, notifications out of scope except as an event. Out of scope: ads, payments, direct messages, the machine-learning internals of ranking. The system is read-heavy and tolerates slightly stale counts, but not lost writes.

Numbers

A back-of-envelope that decides the shape.

Planning figures for the exercise, not facts about any company.

  • Reads: 50 M daily users × 20 page views is 1 B views a day. 1 B ÷ 86,400 is about 11,600 a second on average, and about 35,000 a second at a 3x peak. That is past 20,000 reads a second, so cache and replicas are needed.
  • Content writes: 2% of daily users post a question or answer each day, so 1 M a day. 1 M ÷ 86,400 is about 12 a second.
  • Votes: 10% of daily users cast 5 votes, so 25 M a day. 25 M ÷ 86,400 is about 290 a second, about 870 at peak. Well under 5,000 writes a second, though a viral answer concentrates them on one row.
  • Content storage: 1 M × 2 KB is 2 GB a day, about 730 GB a year. Votes at 30 B each: 25 M × 30 B is 750 MB a day, about 274 GB a year.
  • Read-to-write ratio on content: 11,600 ÷ 12 is roughly 1,000:1.

What the numbers force: one relational primary comfortably handles the writes, so do not shard yet; add a cache and read replicas for the 35,000 peak reads; and put search in its own index because relational full-text search is not the right tool at this scale.

The design

Diagrams first, then components, data and the hard parts.

One primary, a cache, and a search indexReads hit the page cache first. Every write also leaves an outbox row that a worker turns into index and cache updates.
UsersApp servicesanitize, authorizePage cacheTTL about 1 minutePrimary databaserelational + replicasOutbox workerSearch indexElasticsearchrequestpage by question_idread; write + outboxoutbox eventupdate indexinvalidate pagetext search1234567
  1. A user opens a page or posts. The app service sanitizes rich text and checks permissions.
  2. A read looks in the page cache first, keyed by question_id.
  3. On a miss the page is read from the database. A write goes to the primary as a row plus an outbox row in one transaction.
  4. After commit, the outbox row becomes an event for a worker.
  5. The worker updates the search index, which may lag by seconds.
  6. It also invalidates the cached page and bumps topic lists.
  7. Search queries go to the index, then are re-ranked with votes and recency.

Open on the whiteboardAll 2 diagrams on one tidy board, with a step-by-step walkthrough.

Keep the first design simple and name where it would split later.

  • Primary store: relational. Tables for users, questions (question_id, author_id, title, body, status, created_at), answers (answer_id, question_id, author_id, body, created_at, score), votes, topics, question_topics, follows. Content has relations and needs transactions, and a single primary handles about 5,000 writes a second, so it covers this load for a long time. Index answers by (question_id, score desc) so the question page is one range read.
  • Votes. A unique key on (user_id, answer_id) makes voting idempotent: a repeat request upserts the same row instead of counting twice. The vote row is the truth. The answer's displayed count is a derived counter updated asynchronously in small batches, because a viral answer would otherwise make one row the bottleneck.
  • Answer ordering. Rank by a score that combines vote quality, recency and author credibility. For raw votes use a lower confidence bound rather than the plain count, so an answer with 3 of 3 upvotes does not beat one with 900 of 1,000.
  • Cache. Cache the rendered question page (question plus its top answers) keyed by question_id with a short TTL, about a minute, and delete or refresh on edit. Counts may lag. For a viral question, coalesce concurrent misses so only one request goes to the database.
  • Search. Questions (and top answer text) are indexed in a search engine such as Elasticsearch, fed asynchronously from the database through an outbox or change stream. Search is a secondary index and may lag by seconds. Query by text with title boosted, then re-rank with votes and recency.
  • Feed. Content volume is only about 12 new posts a second, so build the home feed at read time: take recent top answers from each topic and person the viewer follows (cached lists per topic), merge, remove already seen items, rank, paginate with a cursor. No fan-out on write needed yet.

Write path: validate, sanitize rich text, write the row and an outbox row in one transaction, commit, and return. A worker consumes the event to update the search index, invalidate the cached page and bump topic lists.

Hard problem one is duplicate questions. At post time, run the title through the search index, show likely matches, and let the asker confirm. Offline, merge duplicates and redirect the old URL to a canonical question, moving answers and votes.

Hard problem two is trust and abuse. User content is an XSS risk, so sanitize on write and escape on output. Enforce authorization on every edit and delete (author, moderator). Rate-limit posting and voting per account and per IP, detect vote rings through unusual patterns, and put new or flagged content into a moderation queue. For anonymous answers, store the real author_id internally and hide it in the API, which keeps moderation possible.

Scaling later: add read replicas first, then shard by question_id once the primary hits roughly the limits above, keeping an answer on the same shard as its question. Keep user and follow data separate.

Trade-offs

What you chose, and when you would flip.

  • Relational vs a NoSQL store for content. Relational gives constraints, transactions and flexible queries; NoSQL gives easier horizontal scale. With 12 content writes a second, pick relational. Flip when storage or write volume passes what one primary and its replicas can hold, which is many terabytes away.
  • Exact vote counts vs eventually consistent counters. Exact counts on one row serialize hot answers. Pick a vote table as truth and an asynchronously updated count. Flip to exact counts if votes carry money or privileges.
  • Feed built at read time vs fan-out on write. Read-time merge is simple and fresh, and works because content volume is low. Fan-out on write wins when per-user feeds must load instantly and follow counts are bounded. Pick read-time now and flip if feed latency exceeds its budget.
  • Search in the database vs a separate index. Database search is one fewer system but weak at relevance and slow at volume. Pick a separate index fed asynchronously, accepting seconds of lag. Flip to database search for a small prototype.

Follow-ups to expect

Where the interviewer pushes next.

  1. How would you stop a coordinated group from voting an answer to the top?
  2. A question goes viral and gets 100,000 views a second. What happens to the cache and the database?
  3. How would you build the autocomplete box that suggests similar questions while someone is typing a title?
  4. How do you handle an edited or deleted answer that is already in feed caches and the search index?
  5. How would you shard the database, and which queries become expensive after you do?

Where candidates slip

The mistakes this question punishes.

  • Reaching for sharding and a fan-out feed at 12 writes a second, instead of using the numbers to justify a single primary.
  • Using SQL LIKE for search.
  • Incrementing a counter column on every vote with no uniqueness rule, so double votes and hot rows both appear.
  • Ranking by raw vote count only.
  • Ignoring spam, XSS and permission checks on edit and delete.
  • Not mentioning duplicate questions, which is the product's central quality problem.
  • Caching pages with no invalidation or TTL story.
  • Using OFFSET paging on a list that changes.
  • Letting a viral question send every cache miss to the database at once.

Have a go before you read.

Interviews reward the sketch you make cold. Clarify out loud, draw it, then compare with the answer.

Now make it stick

Where this was reported

Public pages only. Companies do not confirm these, and they rotate their questions, so treat each link as one person's account or one list's tag.

Read these chapters first