SysDesignPrep.com
Study guide 53 of 183

Modelling comments and nested threads

Storing and serving comment threads at scale: flat versus nested comments, adjacency lists, materialized paths, nested sets and closure tables, loading trees efficiently, sorting by top, new and controversial, pagination of deep threads, counts, edits and deletions, and caching hot threads.

Reading is half of it. See this used in a real interview: walk through Design Reddit →

Comments look simple until they nest: Reddit threads go dozens of levels deep with thousands of replies, and each level must be sorted, paginated and counted. Even flat comments on a viral post become a hot spot. "Design Reddit" and similar questions often spend real time on how comments are stored and loaded. This guide covers the main tree models and the serving tricks.

Flat or nested

  • Flat (Instagram, YouTube top level): comments belong to a post; replies are one level deep at most. Store by (post_id, sort key); paging is straightforward.
  • Nested (Reddit, Hacker News): arbitrary depth. Needs a tree model and a strategy for loading subtrees.

Tree models

ModelStored per commentRead a subtreeInsertNotes
Adjacency listparent_idrecursive query or several round tripstrivialsimplest; recursive CTEs make reads acceptable in SQL
Materialized pathpath like 0001.0042.0107prefix query on path, one index scaneasy (parent path + own id)very practical; path length grows with depth
Nested setsleft and right numbersrange queryexpensive (renumbering)good for read-mostly trees only
Closure tablea row per (ancestor, descendant, depth)join on ancestorinserts one row per ancestorflexible queries; more storage

For comments, the adjacency list plus a materialized path (or just a materialized path) is a strong default: inserting is cheap, and fetching a whole thread or a subtree in tree order is one indexed range scan on (post_id, path). Sorting siblings by score instead of id requires a different approach (below).

Loading threads efficiently

Large threads cannot be loaded entirely:

  • Fetch the top N top-level comments by the chosen sort, then for each, its top few replies down to a limited depth (for example, 3 levels, 3 replies each), with "load more replies" links carrying cursors.
  • Fetch all comments for a post in one query (by post_id) and assemble the tree in the application, if the thread is small enough (a few thousand). Many systems do this and cache the result.
  • For huge threads, precompute the rendered tree for the default sort and cache it, invalidating or refreshing as votes and replies arrive. See caching.

Sorting

Each level is sorted independently:

  • New: by creation time.
  • Top: by score (upvotes minus downvotes, or a confidence-adjusted score).
  • Best: by a lower confidence bound (Wilson score) so a comment with 9 of 10 upvotes ranks above one with 50 of 100 only when the evidence supports it.
  • Controversial: high volume with balanced votes.

See voting and ranking algorithms. Scores change constantly, so sorted views are usually computed in the application or cache rather than by the database index, and refreshed periodically for hot threads.

Counts

"1.2k comments" is read far more than comments are written. Keep a counter per post (and per comment for reply counts), updated asynchronously, eventually consistent. See counting at scale.

Writes and hot threads

A viral thread may receive hundreds of comments per minute and thousands of votes:

  • Write comments to a store partitioned by post_id; very hot posts can be a hot partition, so buffer writes or spread by sub-key if necessary. See hot keys and skew.
  • Batch vote updates and score recomputation instead of updating sorts on every vote.
  • Serve reads from a cache refreshed every few seconds; users accept slight delays in vote counts.
  • Show the user's own new comment immediately (read-your-writes) even if the cache is stale. See consistency models.

Edits and deletions

  • Edits update the body and set an edited flag and timestamp; keep history if moderation requires it.
  • Deleting a comment with replies usually leaves a placeholder ("[deleted]") so the thread structure survives; delete fully if it has no replies.
  • Moderation removals hide content but keep it for appeals and audit. See trust and safety.

Storage choices

In the interview

"Comments are stored per post with parent_id and a materialized path, partitioned by post_id; the default view loads the top 50 top-level comments by 'best' and three levels of top replies, assembled in the comment service and cached for hot threads, refreshed every few seconds; deeper replies load on demand with cursors; counts and scores update asynchronously from vote events." See Design Reddit.

Checklist

  • Flat or nested decided by product needs.
  • Adjacency list plus materialized path (or closure table) for trees.
  • Partial loading with depth and breadth limits and cursors.
  • Per-level sorting with confidence-based scores; cached views for hot threads.
  • Asynchronous counters; batched vote processing.
  • Placeholders for deleted comments with replies; moderation kept for audit.

Open in your browser to sign in

Google does not allow sign-in inside this app's built-in browser. Open this page in Safari and sign in there. The link opens this same page.

Tap the ⋯ or share button at the top or bottom of the screen, then Open in browser. Or copy the link and paste it into Safari.