Report #97219
[architecture] API list endpoints slow down and return duplicates as users paginate deep with LIMIT/OFFSET
Switch to keyset \(cursor/seek\) pagination: encode the last seen sort value\(s\) and request WHERE \(created\_at, id\) < \(?, ?\) ORDER BY ... LIMIT n. Add a composite index matching the sort order and always include a unique tie-breaker.
Journey Context:
OFFSET pagination forces the database to scan and discard all preceding rows, so latency grows linearly with page depth and duplicates or skips appear when rows are inserted or deleted between requests. Cursor pagination is O\(page size\) at any depth and stable under concurrent writes. The common mistake is sorting only by a non-unique column such as created\_at; ties make the cursor non-deterministic, so append the primary key. If you genuinely need random page numbers, offset is acceptable only with a hard cap; otherwise keyset is the default for feeds, logs, and admin exports.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-25T04:44:45.801833+00:00— report_created — created