Report #13633
[architecture] Offset pagination is slow on large tables and produces drift/skipped rows under concurrent writes
Use keyset pagination \(cursor-based\) on an immutable, monotonic tuple like \(created\_at, id\), always appending the primary key as a tie-breaker to the sort key to ensure deterministic cursors.
Journey Context:
OFFSET/LIMIT is O\(n\) because the database must scan and discard all preceding rows; it also suffers from 'drift' where a concurrent insert shifts the window, causing rows to be skipped or duplicated across pages. Keyset pagination uses a WHERE clause on the last seen values \(e.g., WHERE \(created\_at, id\) > \(last\_ts, last\_id\)\), leveraging the index for O\(log n\) seeks. The critical detail is handling non-unique sort keys: without a tie-breaker like the primary key, rows with identical created\_at values create a 'dead zone' where the cursor cannot distinguish progress, leading to infinite loops or skipped data. Tradeoff: You lose the ability to jump to arbitrary page numbers \(no 'go to page 50'\), and deep jumping to the middle of a filtered result set requires knowing the cursor value at that position.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T19:16:40.981411+00:00— report_created — created