100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

How Do You Design a Comment System?

Learn how to design a comment system: threading, cursor pagination, denormalized counters, and async moderation.

mediumQ68 of 224 in System Design Est. time: 5 minsLast updated:
Open Code Lab

Expected Interview Answer

A comment system stores comments as nested or flat records keyed by the parent content ID, uses a database that supports efficient tree or adjacency-list queries (or a materialized-path/nested-set model for deep threading), and layers caching plus pagination on top so a post with thousands of comments still loads quickly and stays consistent under concurrent writes.

Each comment is stored with a reference to its parent content (post/video ID) and, for threaded replies, a reference to its parent comment ID, forming an adjacency list; for very deep or heavily-read threads, a materialized path or closure table can make fetching an entire subtree a single query instead of a recursive one. Comments are paginated (cursor-based, not offset, so new comments don’t shift pages) and sorted by recency, top-voted, or relevance depending on the product. A write path handles comment creation with basic validation, spam/abuse filtering (often async via a moderation queue), and increments denormalized counters (comment count, like count) rather than counting rows live. Read-heavy hot threads are cached (per-page or per-subtree) and invalidated on new writes, and real-time delivery of new comments to active viewers is typically handled via a separate pub/sub or WebSocket layer so it doesn’t block the core write path.

  • Adjacency-list or materialized-path storage supports efficient threaded replies at any depth
  • Cursor-based pagination keeps comment feeds stable even as new comments are added
  • Denormalized counters avoid expensive live counts on high-traffic content
  • Separating moderation and real-time delivery from the write path keeps comment posting fast

AI Mentor Explanation

A comment system is like the stands at a match where fans jot notes on a shared board, each note pinned under the specific incident it reacts to, and replies pinned under earlier notes to form a thread. A steward periodically counts and displays the total note count on a summary sign instead of recounting live every time someone looks. New notes appear at the top for anyone actively watching, but people scrolling through older notes see a stable list that does not jump around. That structured, threaded, counted, and stably paginated layout is exactly how a comment system organizes discussion.

Step-by-Step Explanation

  1. Step 1

    Store comments with parent references

    Each comment stores the parent content ID and, for replies, the parent comment ID, forming an adjacency list (or materialized path for deep threads).

  2. Step 2

    Write with async moderation

    On creation, validate and enqueue the comment for async spam/abuse filtering, then increment a denormalized comment counter.

  3. Step 3

    Paginate with a cursor

    Fetch comments using a cursor keyed on timestamp or vote score, not offset, so newly inserted comments never shift existing pages.

  4. Step 4

    Cache and push updates

    Cache hot comment threads and invalidate on write; push new comments to active viewers over a separate pub/sub or WebSocket channel.

What Interviewer Expects

  • Describes a threading model (adjacency list, materialized path, or closure table) and its trade-offs
  • Uses cursor-based pagination and explains why offset pagination breaks under concurrent writes
  • Mentions denormalized counters instead of live counting for comment/like counts
  • Separates moderation and real-time delivery from the synchronous write path

Common Mistakes

  • Using offset-based pagination that shifts as new comments arrive
  • Recursively querying the whole tree on every read instead of a flatter storage model
  • Counting comments live with COUNT(*) on every page load instead of denormalizing
  • Doing synchronous spam/moderation checks that block comment submission latency

Best Answer (HR Friendly)

A comment system stores each comment with a link to what it is replying to, so replies naturally form threads. To keep things fast, we cache popular threads, use a counter instead of recounting comments every time, and page through comments in a way that does not jump around when new ones come in. Spam checking and live delivery of new comments happen separately so posting a comment always feels instant.

Code Example

Adjacency-list comment schema and cursor pagination (pseudo-code)
// Comment table: id, contentId, parentCommentId, authorId, body, createdAt

async function postComment({ contentId, parentCommentId, authorId, body }) {
  const comment = await db.comments.insert({ contentId, parentCommentId, authorId, body, createdAt: Date.now() })
  await moderationQueue.enqueue(comment.id) // async spam/abuse check
  await db.contents.increment(contentId, "commentCount", 1) // denormalized
  return comment
}

async function getComments(contentId, cursor, limit = 20) {
  // cursor-based: fetch comments older than the last seen createdAt
  return db.comments.find({
    contentId,
    parentCommentId: null,
    createdAt: cursor ? { $lt: cursor } : undefined,
  }).sort({ createdAt: -1 }).limit(limit)
}

Follow-up Questions

  • How would you support sorting comments by “top” (most liked) instead of recency?
  • How would you fetch a deeply nested reply thread efficiently without N+1 queries?
  • How do you keep the denormalized comment counter consistent if the moderation queue later deletes spam?
  • How would you push newly posted comments to viewers currently on the page in real time?

MCQ Practice

1. Why is cursor-based pagination preferred over offset-based pagination for comments?

Offset pagination recalculates position by row count, which shifts under concurrent inserts; cursor pagination anchors to a stable value like timestamp.

2. Why does a comment system typically use a denormalized comment counter instead of COUNT(*)?

Recomputing counts live does not scale for popular content; incrementing a stored counter on write is far cheaper to read.

3. Why is spam/abuse moderation often done asynchronously after a comment is posted?

Async moderation via a queue keeps comment submission latency low while still filtering abuse shortly after posting.

Flash Cards

How are threaded comments typically stored?As an adjacency list (parent comment ID) or, for deep threads, a materialized path/closure table.

Why cursor-based pagination for comments?It keeps pages stable when new comments are inserted, unlike offset pagination which shifts.

Why denormalize the comment count?To avoid an expensive live COUNT(*) on every page load of high-traffic content.

Why handle moderation asynchronously?So spam/abuse checks do not block or slow down the comment submission path.

1 / 4

Continue Learning