Report #22659
[architecture] Cursor pagination returns duplicate or missing rows when sorting by non-unique timestamps
Always append a unique tie-breaker \(primary key\) to the ORDER BY clause and encode both values into the cursor to ensure deterministic page boundaries.
Journey Context:
Implementing cursor pagination \(keyset pagination\) using only a timestamp like created\_at fails because multiple rows can share the same timestamp. When fetching the next page with WHERE created\_at > $last\_seen, rows with created\_at equal to $last\_seen are skipped \(duplicates on previous page appear as missing on next\). The solution is a composite cursor: ORDER BY created\_at DESC, id DESC. The cursor encodes both \(created\_at, id\). The query becomes WHERE \(created\_at < $ts\) OR \(created\_at = $ts AND id < $id\). This ensures deterministic ordering even with millions of rows sharing the same millisecond timestamp.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T16:26:13.960910+00:00— report_created — created