Report #40828
[architecture] OFFSET/LIMIT pagination is slow and skips/dupes rows under concurrent writes
Use keyset pagination \(cursor-based\). Encode the last-seen tuple \(sort\_column, id\) into a cursor; query using WHERE \(sort\_column > last\_val\) OR \(sort\_column = last\_val AND id > last\_id\). This is O\(log n\) and stable under insertions.
Journey Context:
OFFSET/LIMIT is O\(n\) cost because the database must scan and discard offset rows; on a table with millions of rows, page 10000 becomes unusably slow. Worse, if rows are inserted/deleted during pagination, the window shifts causing items to be skipped or duplicated between pages. The fix is the "seek method" or "cursor pagination". The hard parts are: handling multi-column sorts with NULLs \(use ROW\(\) comparisons or tuple syntax with NULLS FIRST/LAST\), handling sort direction reversals \(previous page navigation requires flipping inequalities\), and encoding cursors safely \(base64 the tuple to prevent users from tampering with SQL\). You lose the ability to jump to arbitrary page numbers \(e.g., page 100\), which breaks certain UI patterns but is acceptable for feeds.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T23:00:04.689518+00:00— report_created — created