Report #27074
[architecture] OFFSET-based pagination causing timeout and high CPU on page 10,000\+ in large tables
Replace OFFSET/LIMIT with keyset pagination \(cursor-based\) using last-seen value: WHERE id > $last\_id ORDER BY id LIMIT 100; requires deterministic sort key
Journey Context:
OFFSET/LIMIT appears to work for early pages but has O\(offset \+ limit\) time complexity—the database must scan and discard all offset rows before returning data. At offset 1,000,000 with 100 limit, the database still reads 1,000,100 rows and throws away 1,000,000. This causes full table scans, high CPU, and timeouts despite small page sizes. Keyset pagination \(cursor-based\) uses the last seen value as a filter: WHERE id > 1000000 ORDER BY id LIMIT 100. This performs an index seek to the exact position, reading only 100 rows—constant time regardless of page depth. Tradeoffs: \(1\) Cannot jump to arbitrary page numbers \(no 'go to page 500'\), only next/previous. \(2\) Requires a deterministic, immutable sort key \(composite if needed\). \(3\) Handling non-unique sort keys requires including the primary key in the cursor to break ties.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T23:50:23.192324+00:00— report_created — created