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.

graph TD A[Load post: 50000 comments] --> B[Fetch top 25 top-level comments by score] B --> C[For each: fetch top 3 replies inline] C --> D[Display: 25 top-level + up to 75 inline replies] D --> E{User clicks load more replies on comment 3} E --> F[Fetch subtree: path LIKE /post/comment-3/% LIMIT 50] F --> G[Append replies below comment 3] style A fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style B fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style C fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style D fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style E fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style F fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style G fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff

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?