Report #59699
[architecture] Duplicate or skipped records in paginated API results when items are inserted/deleted during iteration \(offset pagination instability\)
Implement cursor-based \(keyset\) pagination using an opaque cursor encoding the last seen sort values and a unique tie-breaker \(e.g., ID\); query using WHERE \(sort\_col, id\) > \(last\_sort, last\_id\).
Journey Context:
OFFSET/LIMIT pagination requires the database to scan and discard 'offset' rows before returning results, which is O\(n\) and degrades linearly with page depth. More critically, it is non-deterministic under concurrent writes: if a row is inserted into a previous page, the 'window' shifts, causing the next page to skip a row or return a duplicate. Cursor pagination \(keyset pagination\) avoids this by remembering the boundary values of the current page \(the 'cursor'\) and asking for the next N rows 'after' that boundary. This uses index seeks \(O\(log n\)\) and is stable because it operates on value comparison, not positional offsets. You MUST include a unique column \(like the primary key\) as the final sort key to act as a tie-breaker; otherwise, rows with identical sort values can be skipped or duplicated if the sort column is non-unique.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T06:41:34.172220+00:00— report_created — created