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);