API Pagination (Cursor vs Offset)
Strategies for breaking large result sets into pages, with cursor-based pagination offering stable results and offset-based offering simplicity.
Description
API pagination divides large collections into manageable pages to limit response size and database load. Offset-based pagination (e.g., ?offset=40&limit=20) is intuitive and supports random page access but suffers from well-known issues: skipped or duplicated records when the underlying data changes between page requests, and degrading database performance because OFFSET requires scanning and discarding rows. For large datasets, OFFSET 100000 can be extremely slow.
Cursor-based pagination (also called keyset pagination) solves these problems by encoding a pointer to the last item returned -- typically the sort key values -- into an opaque cursor token. The next page is fetched using a WHERE clause (e.g., WHERE created_at > $cursor_timestamp AND id > $cursor_id) rather than OFFSET, which is both stable against insertions/deletions and performant because it uses an index seek rather than a scan. The trade-off is that cursors don't support jumping to arbitrary pages.
In practice, cursor-based pagination is strongly preferred for any dataset that changes frequently or grows large. The cursor should be opaque (base64-encoded) so the server can change its internal format without breaking clients. The response should include a next_cursor field (null when no more pages exist) and a has_more boolean. The Relay connection specification provides a well-established convention for cursor pagination in GraphQL contexts.
Prompt Snippet
Implement cursor-based pagination for all list endpoints using an opaque base64-encoded cursor containing the last record's composite sort key (created_at, id). Return a response envelope with { data: [...], next_cursor: string | null, has_more: boolean }. Support a limit query parameter (default 20, max 100). Generate the WHERE clause as (created_at, id) > ($cursor_ts, $cursor_id) with a matching composite index. Reserve offset pagination only for admin/backoffice UIs that need page-number navigation and operate on small, stable datasets.Tags
Related Terms
API Filtering & Sorting
Conventions for allowing API consumers to filter collection results by field values and control the sort order via query parameters.
Response Envelope Pattern
Wrapping API responses in a consistent top-level structure with data, metadata, and error fields for predictable client parsing.
REST API Conventions
A set of architectural constraints and naming conventions for designing consistent, predictable HTTP APIs around resources.