Card 04/ 08
Offset vs Cursor Pagination
Page numbers and simplicity, against speed on deep pages and stable results.
Offset pagination counts rows to skip; cursor pagination points at the last row seen. Offsets let a reader jump to any page number but slow down on deep pages and slip when rows are added or removed. Cursors stay fast and stable on any page but can only move forward from where the reader is.
| Axis | Offset | Cursor |
|---|---|---|
| Jump to page 12 | Yes, offset 275 at 25 a page | No; walk pages 1 to 11 |
| Cost of a deep page | Grows with the offset | Same on every page, with an index |
| Rows added while paging | Rows are skipped or repeated | No gaps or repeats |
| Effort to build | One clause, and easy to read | A unique sort key, an index, and an encoded token |
Use it when
- Readers jump to page numbers, as in an admin table or search results
- The data changes rarely while someone pages through it
- Tables are small enough that deep pages stay cheap
Avoid it when
- The list is a feed with constant inserts at the top
- Clients page deep into a large table, such as an export
Use it when
- The list scrolls forever, as in a feed or a timeline
- Rows are inserted or deleted while readers page
- Clients walk every page, as an export or a sync does
Avoid it when
- Readers need to jump to an arbitrary page number
The tempting mistake. Choosing offsets for a feed because they are simpler. A feed is the case offsets handle worst: new posts arrive at the top all the time, so every page shifts, and readers who scroll far make the database skip ever more rows.
So use offsets where readers jump to page numbers and the data holds still, and cursors wherever readers scroll, sync, or page through data that changes.
- System Design
- API Design
- Performance
← → move through sections and cards