skip to content

API pagination: cursor vs offset


  • Stable under inserts/deletes
  • Uses an opaque cursor (e.g., last seen id + sort key)
  • Easy to cache and resume
SELECT *
FROM items
WHERE (created_at, id) < (:created_at, :id)
ORDER BY created_at DESC, id DESC
LIMIT 50;

Offset pagination (avoid at scale)

  • Can skip/duplicate rows when data changes
  • Gets slower as offset grows
If you need “page numbers”, store cursors per page server-side.