Report #4315
[architecture] OFFSET pagination becomes slow on deep pages in PostgreSQL/MySQL
Implement keyset pagination \(cursor-based\): Instead of OFFSET, use WHERE indexed\_column > last\_value\_from\_previous\_page ORDER BY indexed\_column LIMIT n. For multiple sort columns, use row value comparisons: WHERE \(a, b\) > \(x, y\).
Journey Context:
OFFSET requires the database to scan and discard N rows before returning results, making it O\(n\) time complexity. At high offsets \(page 10000\+\), queries that normally take milliseconds can take seconds. Keyset pagination uses the index to seek directly to the starting point \(O\(log n\)\), but sacrifices the ability to jump to arbitrary page numbers \(no 'Go to page 50'\). A critical complexity arises with multi-column sorting \(ORDER BY created\_at, id\); simple cursor encoding fails because \(created\_at, id\) > \(x, y\) requires proper tuple comparison syntax which varies by database \(PostgreSQL supports row values, MySQL requires more complex boolean logic\). Additionally, rows can be missed or duplicated if the sort key values change during pagination.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T19:13:00.768756+00:00— report_created — created