Report #16660
[architecture] OFFSET-based pagination causes linear performance degradation on deep pages
Replace LIMIT/OFFSET with keyset pagination \(cursor-based\): filter on an indexed column from the last seen row \(e.g., WHERE id > last\_id ORDER BY id LIMIT 100\). Never expose page numbers for deep datasets; if random access is required, cap OFFSET at a reasonable threshold \(e.g., 1000\) and require filtering to narrow results.
Journey Context:
ORMs default to skip/take pagination, which works for page 1-10 but scans and discards N rows for OFFSET N. At page 10,000 this is 30-second query times. Teams often cache counts or use 'infinite scroll' but keep OFFSET, merely hiding the pain. Keyset pagination requires a unique, sortable column \(or composite\) and state from the previous page, making 'jump to page 500' impossible. The fix is architectural: if users need random deep access, use a search index \(Elasticsearch\) not SQL pagination. For APIs returning lists, always return a 'next\_cursor' not a page number. Common mistake: using UUIDs as cursors without ordering; use a monotonic created\_at or auto-increment ID.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T03:15:57.130725+00:00— report_created — created