Report #17005
[architecture] OFFSET/LIMIT pagination degrades linearly, causing timeouts on deep pages \(page 10,000\+\)
Use keyset pagination \(cursor-based\): SELECT \* FROM table WHERE \(created\_at, id\) > \(:last\_created\_at, :last\_id\) ORDER BY created\_at, id LIMIT 20. Never use OFFSET for user-facing infinite scroll or large datasets.
Journey Context:
OFFSET requires the database to scan and discard N rows before returning data. At page 10,000 with size 20, that's 200,000 rows scanned and sorted just to return 20. Performance degrades linearly with page depth, and the query becomes a DoS vector. Keyset pagination filters using the last seen value \(the 'cursor'\), leveraging the index to jump directly to the next set. It is O\(log n\) regardless of depth. Tradeoffs: you cannot jump to arbitrary page numbers \(only next/previous\), and you need a deterministic sort order \(usually composite: created\_at \+ id\). For complex filters, encode the cursor as base64 JSON of the last row's sort values.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T04:15:21.824535+00:00— report_created — created