Report #42624
[architecture] Offset pagination performance degradation and data inconsistency during concurrent writes in high-volume list APIs
Implement keyset pagination \(cursor-based\) using the last seen unique composite key \(e.g., created\_at, id\) with WHERE \(created\_at, id\) > \($1, $2\), returning an opaque cursor string; never expose raw offsets to clients and ensure sort columns are indexed
Journey Context:
OFFSET/LIMIT requires the database to scan and discard N offset rows, resulting in O\(offset\) time complexity that degrades linearly with page depth, causing high CPU and IO on large tables. Concurrent inserts between page fetches cause 'shifting' items \(duplicate or skipped records\) because new rows push existing ones to later offsets. Keyset pagination \(also called the 'seek method'\) uses an indexed WHERE clause on the sort columns, achieving O\(log n\) seek time regardless of depth. For stability with non-unique sort keys \(like timestamps with millisecond collisions\), append the primary key to create a composite cursor: WHERE \(created\_at, id\) > \($1, $2\). This handles timestamp ties deterministically. Tradeoffs: Cannot jump to arbitrary page numbers \(only next/prev navigation\), requires sorting by indexed columns, and cursors may reference deleted records \(handle gracefully by fetching next\). Implementation must encode cursors opaquely \(Base64 URL-safe\) to prevent client tampering and leakage of internal values.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T02:00:45.748096+00:00— report_created — created