Report #10825
[architecture] Pagination strategy for high-velocity tables with millions of rows \(OFFSET performance degradation\)
Never use OFFSET/LIMIT for user-facing deep pagination; implement cursor-based \(keyset\) pagination using a composite cursor of \(last\_seen\_timestamp, id\) with an index on \(created\_at DESC, id ASC\). Handle cursor stability by requiring an immutable tie-breaker \(UUID/bigint ID\) and document that results may shift if records are deleted \(or use an immutable 'cursor token' table for strict consistency\).
Journey Context:
OFFSET has O\(n\) cost—the database must scan and discard all offset rows, making page 1000 as slow as reading 1000\*limit rows. In high-velocity tables, OFFSET also causes duplicates/skips because new inserts shift the window \(phantom rows\). Cursor pagination uses the index to jump directly to the record \(O\(log n\)\). The common implementation error is using timestamp alone as the cursor—this fails when two rows have identical timestamps \(common with bulk inserts\), requiring a composite \(timestamp, id\) cursor. The tie-breaker ID must be monotonic \(bigint\) or lexicographic \(UUID v7\) to maintain ordering.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T11:45:37.340688+00:00— report_created — created