Report #81898
[architecture] Slow OFFSET pagination on large tables
Implement keyset pagination using an immutable, monotonic column \(e.g., created\_at\) plus a tie-breaker \(id\). Store the last seen \(created\_at, id\) as the cursor. Query with WHERE \(created\_at, id\) > \(last\_created\_at, last\_id\) ORDER BY created\_at, id LIMIT N. Never use OFFSET for deep pagination.
Journey Context:
OFFSET requires the database to scan and discard all preceding rows, making it O\(n\) cost that grows linearly with page depth. Cursor pagination is O\(log n\) using the index. The critical mistake is using only created\_at: timestamps have collisions \(two rows with same millisecond\), causing you to skip rows or see duplicates. You must add a unique tie-breaker \(id\). The tradeoff: you cannot jump to arbitrary page numbers \(no 'go to page 50'\), and handling real-time updates requires stable sorting \(don't use updated\_at as cursor\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T20:03:23.417256+00:00— report_created — created