← ClaudeAtlas

cursor-pagination-designlisted

Playbook for designing cursor (keyset) pagination on list endpoints: cursor encoding, response envelope, query parameter contract, and the migration path away from offset pagination.
mcorbett51090/RavenClaude · ★ 7 · Web & Frontend · score 65
Install: claude install-skill mcorbett51090/RavenClaude
# Cursor Pagination Design ## When to Use This Skill Use whenever you are building or reviewing a list endpoint. Default to cursor (keyset) pagination. Use offset/page only when: the dataset is static, or the consumer requires random-access page-jumping (e.g. a UI with a page-number picker on a dataset guaranteed < 10 000 rows). Document the trade explicitly when you choose offset. ## Why Cursor Beats Offset | Concern | Offset/Page | Cursor (Keyset) | |---|---|---| | Deep-page performance | Full `OFFSET N` scan — degrades O(N) | `WHERE id > cursor` — index seek, O(1) | | Consistency during mutations | Rows inserted/deleted shift pages → duplicates/skips | Cursor anchored to a row; inserts/deletes after it are invisible | | Real-time / high-write tables | Unreliable | Stable | | Random-access (jump to page 42) | Supported | Not supported — use if required | ## Response Envelope ```json { "data": [ { "id": "u_01", "name": "Alice" }, "..." ], "pagination": { "nextCursor": "eyJpZCI6InVfMTAwIn0", "hasMore": true, "pageSize": 50 } } ``` | Field | Type | Notes | |---|---|---| | `data` | array | The page of results. | | `pagination.nextCursor` | string\|null | Opaque base64-encoded cursor. `null` when no more pages. | | `pagination.hasMore` | boolean | Convenience flag (derived from `nextCursor != null`). | | `pagination.pageSize` | integer | Actual count returned (≤ requested `limit`). | Do not expose `total` by default — a COUNT(*) on large tables is expen