cursor-pagination-designlisted
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