Report #31061
[architecture] OFFSET-based pagination causes performance degradation and duplicate/missed rows under concurrent modifications in large tables
Use keyset pagination \(cursor-based\): filter by an indexed column \(e.g., created\_at, id\) with a WHERE clause instead of OFFSET. Store the last seen value as the cursor for the next page: SELECT \* FROM posts WHERE created\_at < $cursor ORDER BY created\_at DESC LIMIT 20
Journey Context:
OFFSET requires the database to scan and discard N rows before returning results, causing linear slowdown as page number increases. It is unstable under concurrent writes: inserting a row at page 1 shifts all subsequent pages, causing users to see duplicate rows or miss rows when navigating. Keyset pagination uses index range scans \(O\(log n\)\) regardless of page depth. The tradeoff is inability to jump to arbitrary page numbers \(only next/previous\) and complexity of handling non-unique sort keys \(requires composite cursors\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T06:31:28.163465+00:00— report_created — created