Skip to main content

๐Ÿ“„ Pagination

How to design and implement pagination for API, data grids, and scrolling content.

Overviewโ€‹

Offset-basedCursor-based
DefinitionUses a specific number (offset) to indicate the starting point of the data to be fetched.Uses a unique identifier (cursor) to mark the position in the dataset.
Use CasesSimple data retrieval scenarios where the dataset is relatively small1 and static.Large datasets, real-time data, or when data changes frequently.
ProsEasy to implement and understand.More efficient for large datasets and reduces the risk of data inconsistency.
ConsProne to data drifting & Performance degrade when scaledComplex to implement. Can't jump to arbitrary pages.

Things to Considerโ€‹

  • Performance: Fast is always charming. Locate the bottlenecks and optimize them.
    • Sometimes backend spend time querying the database
    • Sometimes complex frontend rendering takes times.
    • Either way, page_size must have a reasonable limit.
  • User Experience
    • Do user need to jump to arbitrary pages?
    • Do you need Sorting, filtering, and searching? Where to apply them?
  • Data Consistency
    • How often does the data change? By same user or other users on different clients?
    • How critical is it to avoid duplicates or missing items? (maybe some drifting is acceptable?)

Decision Makingโ€‹

  • If data may be drifting โ†’ cursor-based
  • If data is relatively static and small โ†’ offset-based
  • If you need to jump to arbitrary pages โ†’ offset-based
  • Infinite scrolling โ†’ cursor-based

Cursor Checklistโ€‹

  • Include all necessary information, e.g., unique ID, timestamp, sorting, filters, etc.
  • Unique
  • Opaque: Clients should not infer any meaning from the cursor value
  • Idempotent: Retried requests with the same cursor must return the same page
  • Signed with HMAC
  • Support has_more to indicate if there are more pages
  • Support bidirectional scrolling with next_cursor and prev_cursor
  • For GraphQL, use Relay Cursor Connections Specification

Footnotesโ€‹

  1. TanStack Table loads 100,000 rows and works just fine. โ†ฉ