Stack Overflow
Q&A Platform
Design a question-and-answer site with votes, accepted answers, tags and a reputation score that follows the real Stack Overflow rules.
Overview
A question-and-answer site lets a user ask a question, lets others answer it, and lets the crowd vote on both. The asker marks one answer as accepted. Every one of those actions changes the reputation score of the people involved, and that score in turn decides what a user is allowed to do. The interview version of this problem asks you to model the content, the votes and the reputation rules so that they stay correct when many users act at once.
The problem is rated hard because the pieces depend on each other. A vote is not just a counter: it changes the author's score, sometimes the voter's score, and it can be changed or taken back later, which must undo exactly what it did. The accepted answer can be switched, which must move points from one answerer to another. Interviewers use this problem to see whether you keep the reputation rules in one place, whether you can undo an action without leaving a trace, and whether you can make it safe for many threads.
The rules used below are the real ones from the Stack Overflow help center. A question or answer that is voted up gives its author 10 points. A downvote costs the author 2 points, and a downvote on an answer also costs the voter 1 point; downvoting a question is free. An accepted answer gives its author 15 points and the asker 2. Everyone starts at 1 point and can never go below 1. Reversing a vote reverses its reputation change. Voting up needs 15 points and voting down needs 125.
Scoping the problem
The answers to these questions decide how much you build, so ask them before drawing anything.
- Which reputation rules apply? — They are the heart of the design; agree on a small table — Upvote 10, downvote 2, accept 15 plus 2
- Can a user change or take back a vote? — Every rule then needs an exact reverse — Yes, both
- Can the asker switch the accepted answer? — Points move from the old answer's author to the new one — Yes
- Do comments carry votes or reputation? — Decides whether Comment is a Post or a simpler leaf — Comments do not change reputation
- Do privileges depend on reputation? — Adds a check before every vote — Yes: 15 to vote up, 125 to vote down
- Can users vote on their own posts? — A rule the vote method must enforce — No
- Many threads at once? — Locks on each post and each user — Yes
- Search: keywords, tags, author? — Each is a small strategy over the questions — All three
Core entities
Content is the base of everything a user writes. A Post is content that can be voted on, so Question and Answer extend it. A Comment is content that cannot be voted on, so it stays a leaf under Content and never touches reputation.
How a vote changes reputation
A post does not know what a vote is worth. It records the vote under its lock, then publishes an event. The ReputationPolicy is the only class that knows the point values; it subscribes to the bus and adjusts the users. Changing a vote is two events: retract the old one, cast the new one.
The trace below follows the demo in the implementation. Bob starts at 50 and Carol at 200.
- 1 — Carol upvotes Bob's answer — 60 — 200 — Upvote on an answer: +10 to the author
- 2 — Carol clicks upvote again — 60 — 200 — Same vote twice is a no-op
- 3 — Carol changes it to a downvote — 48 — 199 — Undo +10, then -2 to author and -1 to voter
- 4 — Carol retracts the downvote — 50 — 200 — Both sides reversed
- 5 — Alice accepts Bob's answer — 65 — 200 — +15 to Bob, +2 to Alice
- 6 — Alice switches to Carol's answer — 50 — 215 — Bob loses 15, Carol gains 15, Alice keeps her 2
What you will be able to do
- Draw the Content, Post, Question, Answer and Comment hierarchy and say why Comment is not a Post.
- Keep every point value in one observer so a rule change touches one class.
- Implement vote change and vote retraction so that each reverses exactly what it did.
- Explain why the floor at 1 point makes a reversal inexact and how a ledger fixes it.
- Make voting safe for many threads with a lock per post and a lock per user, and say what a global lock would cost.
Functional requirements
- A user asks a question with a title, a body and tags; other users answer it
- Users vote a question or an answer up or down, change the vote, or take it back
- The asker marks one answer as accepted and may switch to another answer later
- Reputation follows the published rules: upvote +10 to the author; downvote -2 to the author and -1 to the voter on answers only; accepted answer +15 to its author and +2 to the asker
- A user needs 15 points to vote up and 125 to vote down, may not vote on their own posts, and never drops below 1 point
- Comments attach to a question or answer and never change reputation
- Search questions by keyword, by tag or by author
Non-functional requirements
- Votes and reputation stay exact when many users act at the same time
- Every reputation change is reversible: retracting or changing a vote leaves no trace
- The point values live in one class so a rule change is a one-line edit
- Voting on one post never blocks voting on another post
Interview questions
- Why route reputation through an observer instead of updating it inside vote() and accept()?
- Reputation never drops below 1. Why does that make vote reversal inexact, and what would you do about it?
- How would you add the daily cap of 200 reputation from votes?
- How do you keep votes and reputation correct with many concurrent users, and why not one global lock?
- Is a votes dict on the post enough, or do you need a Vote entity?
Sign up free to read the full topic
More Low-Level Design topics
Start free on Cariara · Coding problems · System design studio