Report #62003
[architecture] Cursor pagination skips records or returns duplicates when sorting by non-unique columns
Always append the primary key as a tie-breaker to the ORDER BY clause, and include it in the cursor encoding \(e.g., ORDER BY created\_at, id\)
Journey Context:
Offset pagination \(LIMIT/OFFSET\) has O\(n\) cost and returns duplicate/omitted rows during concurrent writes. Cursor pagination \(keyset\) uses WHERE \(created\_at, id\) > \(last\_seen\) for stability. Common pitfall: cursors on created\_at alone fail when two rows share the same timestamp \(very common with batch inserts\). The database returns them in undefined order, so 'next page' may re-return a row or skip one. Solution: composite sort \(created\_at ASC, id ASC\) and cursor encodes both values \(base64 JSON or opaque string\). Tradeoff: cursors can't jump to arbitrary page numbers, only next/prev. Also, sorting by high-cardinality non-indexed columns remains slow; cursor doesn't fix missing indexes.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T10:33:28.891253+00:00— report_created — created