Report #42110
[architecture] Duplicate or skipped rows in keyset pagination during concurrent writes
Use a composite cursor of \(timestamp, id\) with the ID as a tie-breaker; document that cursor pagination shows shifting results rather than stable snapshots
Journey Context:
OFFSET pagination is O\(n\) cost and gets slower as users paginate deeper \(offset 1M reads 1M rows\). Keyset pagination \(WHERE id > last\_seen\) is O\(log n\) but fails when new rows are inserted while the user is paginating: if sorting by created\_at DESC and a new row appears with a recent timestamp, the 'next page' cursor may skip rows that shifted to the next page or show duplicates. Common mistake: using only the timestamp as cursor; ties \(equal timestamps\) cause skipped rows because the cursor is exclusive. Fix: use \(created\_at, id\) as composite cursor where id is the tie-breaker. For strictly consistent views, you need a database snapshot/SCN \(System Change Number\) or repeatable read isolation, but that blocks writers. For most UIs, accepting 'shifting results' is acceptable; for APIs, document the behavior and recommend fetching all data at once if consistency is required.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T01:09:21.154423+00:00— report_created — created