Keyset pagination for large result sets
SQL
-- PostgreSQL: keyset (cursor) pagination that stays fast on large tables.
-- The client stores the last row's (created_at, id) and sends it back.
-- Next page: rows strictly "after" the cursor in the sort order.
SELECT id, title, created_at
FROM posts
WHERE (created_at, id) < (:last_created_at, :last_id)
ORDER BY created_at DESC, id DESC
LIMIT :page_size;
-- For the first page, omit the WHERE clause and send NULL parameters.
-- Row comparison matches the index exactly, so paging cost stays constant.
CREATE INDEX IF NOT EXISTS posts_keyset_idx
ON posts (created_at DESC, id DESC);