Report #13112
[architecture] Duplicate or skipped items in paginated lists during concurrent writes \(offset pagination instability\)
Replace OFFSET/LIMIT with keyset pagination \(cursor-based\) on an immutable, monotonic composite key \(e.g., \`created\_at, id\`\). Query: \`WHERE \(created\_at, id\) > \($1, $2\) ORDER BY created\_at ASC, id ASC LIMIT 20\`. Encode the last tuple as an opaque cursor for the next page.
Journey Context:
OFFSET-based pagination is O\(n\) for large offsets \(database must scan and discard rows\) and unstable under concurrent writes: if a new item is inserted at the beginning while the user is on page 2, the item previously at the top of page 2 shifts to page 1, causing it to be skipped when the user clicks 'Next'. Cursor pagination avoids this by querying relative to the last seen value, unaffected by insertions elsewhere. The composite key \(timestamp \+ ID\) is required because \`created\_at\` alone may have duplicates \(two items created in the same millisecond\), causing cursor ambiguity. The downside is inability to jump to arbitrary page numbers \(no 'go to page 5'\) and complexity when sorting by non-monotonic columns \(e.g., 'last\_name' changes, breaking cursors\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T17:47:28.286720+00:00— report_created — created