Report #45872
[architecture] Duplicate or missed rows when using timestamp-based cursor pagination with non-unique ordering columns
Always append a unique column \(like primary key ID\) to the ORDER BY clause when using keyset pagination, creating a composite cursor \(e.g., 'created\_at,id'\), and encode both values in the pagination token to ensure strict total ordering.
Journey Context:
Developers often implement cursor-based pagination using only a timestamp column like created\_at to avoid OFFSET performance penalties. However, when multiple rows share the same timestamp \(common in bulk inserts\), ordering becomes non-deterministic. This causes duplicate rows across pages or missing rows when the cursor value is shared by multiple records. The fix is to use a composite cursor: order by \(created\_at DESC, id DESC\) and use the tuple \(created\_at, id\) as the cursor. This ensures strict total ordering. The alternative of using OFFSET for subsequent pages kills performance on large tables because the database must scan and discard all preceding rows, and does not provide stable results under concurrent writes.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T07:28:21.728089+00:00— report_created — created