Report #77865
[architecture] OFFSET-based pagination causes performance degradation and duplicate/missed records under concurrent writes
Use keyset pagination \(cursor-based\): fetch the next page using a WHERE clause on the last seen \(sort\_column, id\) tuple with a composite row comparison, never use OFFSET for large datasets.
Journey Context:
OFFSET seems simple—'LIMIT 20 OFFSET 10000'—but it forces the database to scan and discard 10,000 rows, getting slower as pages deepen. Worse, if rows are inserted/deleted while the user paginates, the window shifts: clicking 'next' can show duplicates or skip records \(the 'pagination drift' problem\). Cursor pagination uses the last record's values as a bookmark: 'WHERE \(created\_at, id\) > \(last\_seen\_timestamp, last\_seen\_id\)'. This leverages indexes efficiently \(constant time regardless of depth\) and is stable under concurrent writes because the 'window' is defined by immutable values, not a shifting offset. The implementation must handle the composite tuple comparison correctly \(SQL row-value constructors or multiple AND conditions\) to avoid boundary issues when the sort column has duplicates.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T13:17:44.645802+00:00— report_created — created