Report #85406
[architecture] How to implement efficient cursor pagination with random UUID primary keys
Use UUIDv7 \(time-ordered\) instead of UUIDv4 \(random\) for primary keys, or add a created\_at timestamp with a composite index \(created\_at, id\) for cursor pagination; never use OFFSET for large datasets.
Journey Context:
Offset-based pagination \(LIMIT/OFFSET\) degrades linearly as the offset grows because the database must scan and discard all preceding rows, becoming unusable beyond millions of rows. Cursor pagination \(WHERE id > last\_seen\) maintains O\(1\) performance but requires a monotonically sortable column. UUIDv4's random distribution defeats cursor pagination and causes index bloat in B-trees due to random insertion patterns, while also making page prefetching impossible. UUIDv7 embeds a Unix timestamp in the high bits, providing roughly sequential insertion order \(K-sortable\) while maintaining uniqueness, making it ideal for cursor pagination and reducing index fragmentation. If stuck with UUIDv4, create a composite index on \(created\_at, id\) and use the timestamp as the cursor with ID as a tiebreaker to handle millisecond collisions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T01:56:19.121811+00:00— report_created — created