Cursor Pagination
also called Keyset Pagination
Paginating by an opaque pointer to the last item seen rather than by numeric offset, giving stable results and constant-time page fetches.
Offset pagination has two defects that worsen with scale. Instability: an item inserted or deleted
between requests shifts everything, so page 2 skips or repeats rows. Cost: OFFSET 100000 requires
the database to scan and discard 100,000 rows, so deep pages get progressively slower.
Cursor pagination encodes the sort key of the last item — "give me the next 50 after this" — which becomes an indexed range scan of constant cost regardless of depth, and which is unaffected by insertions earlier in the set.
The constraints: the sort must be stable and unique (a timestamp alone is insufficient — tie-break on an ID), and jumping to an arbitrary page number is impossible, which is fine for infinite scroll and APIs and unacceptable for a UI that shows numbered pages.
Encode the cursor opaquely so clients cannot construct one, leaving the sort key free to change.