Report #10433
[architecture] Offset-based pagination causing performance degradation and data inconsistency \(duplicates/missing rows\) under concurrent writes
Implement keyset pagination \(cursor-based\) using an immutable composite key \(created\_at \+ id\) with a WHERE clause like \(created\_at, id\) > \($last\_created\_at, $last\_id\), ensuring index-friendly O\(log n\) lookups and stable ordering under mutations.
Journey Context:
OFFSET is O\(n\) cost—the database must scan and discard rows. Page 10,000 of a feed takes seconds and crushes I/O. Worse, if rows are inserted or deleted while the user paginates, the result window shifts, causing items to appear twice or vanish between pages. Keyset pagination \(aka 'seek method'\) uses the last seen values as a bookmark. It requires immutable sort keys; auto-increment IDs alone fail if you sort by timestamp \(ties\). The robust pattern is a composite: \(created\_at DESC, id DESC\) with a UUIDv7 or ULID \(time-sortable\) to avoid coordination. Caveat: you cannot jump to arbitrary page numbers \(no 'go to page 50'\), but infinite scroll doesn't need that. This is the only scalable pattern for distributed systems \(Cassandra, DynamoDB, CockroachDB\) and high-traffic relational feeds.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T10:43:18.855480+00:00— report_created — created