Comment Pagination at Scale
A viral post on Reddit has 50,000 comments. You can’t load them all at once. You need pagination — but comment pagination is harder than standard cursor-based pagination because the data is a tree, not a list. Loading “the next 20 comments” in a threaded comment system requires deciding what “next” means for hierarchical data.
Top-Level Pagination#
The simplest strategy: paginate only top-level comments. Load the first 25 top-level comments. Each top-level comment shows its top 3 replies inline. A “load more replies” button fetches the rest of a specific comment’s subtree on demand.
This is Twitter’s approach: top-level tweets paginate; reply threads load lazily. It avoids the tree-ordering problem by treating each subtree as independent.
Cursor: the top-level comment’s sort key (score or timestamp). WHERE post_id = X AND parent_id IS NULL AND score < cursor ORDER BY score DESC LIMIT 25. Standard cursor pagination on a filtered set.
Lazy Subtree Loading#
When a user clicks “load more replies,” fetch the subtree rooted at that comment. With path enumeration: WHERE path LIKE '/root/parent/%' ORDER BY path. The path ordering gives depth-first display order naturally. Depth limit: stop fetching beyond 8 levels deep; show a “continue thread” link instead.
Sorting Within Levels#
Comments sort differently from flat lists. Options:
By score (upvotes - downvotes): best comments surface first. Sort key per level, not globally. The highest-scored top-level comment might have a lower-scored reply that appears before the second top-level comment. This requires the tree structure: you can’t just sort all 50,000 comments by score.
By time (chronological): simpler, but buries good responses. New comments don’t surface if the thread is old.
Reddit uses “best” sort: a Wilson score interval that balances upvote count with statistical confidence. A comment with 100 upvotes and 10 downvotes ranks higher than one with 50 upvotes and 0 downvotes.
Caching#
Top-level comment pages for popular posts are heavily cached. The first page (top 25 by score) changes infrequently once a post is a few hours old: new comments rarely push into the top 25. Cache with a 5-minute TTL, serve stale on cache miss while recomputing.
Per-subtree caching is less effective: subtrees are more varied and less frequently accessed, making cache hit rates lower.
At Salesforce#
Salesforce Case comments had a similar structure: cases had threaded comments from support agents and customers. We used flat pagination (no nesting) with parent_comment_id stored for display purposes. Fetching a case’s comments was a single ORDER BY created_at query. Nesting was rendered client-side by grouping on parent ID. For our max case size (a few hundred comments), this was fast enough without a tree query strategy.
What I’m Learning#
Comment pagination works best when you accept that you can’t load everything at once and design around it structurally: paginate top-level, lazy-load subtrees, limit depth. The hardest part is usually sort order within levels, which requires understanding the tree structure rather than treating comments as a flat list.
Have you built comment systems and what pagination strategy kept the database queries manageable at scale?