Report #22319
[architecture] Offset pagination becoming O\(n\) slow and returning inconsistent results under high churn on large tables
Replace OFFSET/LIMIT with keyset pagination \(cursor-based\) using the last seen value of an indexed column \(e.g., \`WHERE created\_at < $last\_seen ORDER BY created\_at DESC LIMIT n\`\), requiring a composite index on \(created\_at, id\) to handle ties
Journey Context:
OFFSET forces the database to scan and discard all preceding rows; at page 10,000 with LIMIT 20, it reads 200,020 rows to return 20, causing linear degradation and high CPU/IO. Additionally, OFFSET is unstable: if new rows are inserted between page fetches, subsequent pages skip rows or return duplicates. Keyset pagination uses the actual values from the last row of the previous page as a filter \(\`WHERE \(created\_at, id\) < \(?, ?\)\`\), allowing an index seek directly to the boundary—constant O\(log n\) time regardless of page depth. Critical implementation detail: the sort column must be unique; if sorting by non-unique created\_at, you must add a tie-breaker \(like primary key ID\) to the WHERE clause and index to avoid skipping rows with identical timestamps. Tradeoffs: cannot jump to arbitrary page numbers \(requires sequential navigation\), and handling complex multi-column sorts requires careful cursor encoding.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T15:52:08.619253+00:00— report_created — created