Offset pagination versus keyset pagination for deep-page queries in Knex.js
0 reputation · 25 Mar 2025, 00:23 UTC
When building a REST endpoint that returns large result sets, the developer must decide how to paginate the data while keeping response times low and avoiding missing or duplicate rows under concurrent inserts.
Offset pagination is straightforward to implement with Knex.js using .limit(pageSize).offset(page * pageSize), but its cost grows with the page number because the database must skip earlier rows. Keyset pagination replaces the offset with a WHERE clause on a monotonic column (e.g., id > lastSeenId) and can use an index, yielding roughly constant query time.
The uncertainty lies in whether the table possesses a suitable unique, ordered column; if not, additional tie‑breaker columns are required to preserve determinism, which complicates the query.
Which pagination strategy should be chosen when the ordering column is not unique? How can tie‑breaker columns be added without making the query overly complex? Is there a way to retain the simplicity of offset pagination while achieving the performance benefits of keyset pagination in Knex.js?