Build the mental model
SQL does not guarantee result order without `ORDER BY`. `LIMIT/OFFSET` is simple pagination, but large offsets become slow and concurrent inserts can cause duplicates or skipped rows. Use a stable tie-breaker, and prefer keyset pagination for large feeds.
Connect it to a real scenario
List published tutorials newest first, breaking equal timestamps by descending ID for deterministic results. Search input must be passed as a parameter by the application rather than concatenated into SQL. This lesson focuses on query semantics; the project chapter adds parameterization.
Try the working example
-- First page
SELECT tutorial_id, title, published_at
FROM app.tutorials
WHERE is_published = true
ORDER BY published_at DESC, tutorial_id DESC
LIMIT 10;
-- Next keyset page: values come from the last visible row
SELECT tutorial_id, title, published_at
FROM app.tutorials
WHERE is_published = true
AND (published_at, tutorial_id) <
(TIMESTAMPTZ '2026-08-01 10:00:00+00', 42)
ORDER BY published_at DESC, tutorial_id DESC
LIMIT 10;Published tutorials are returned in stable, page-sized batches.5-minute try-it
Write a keyset-pagination query for active users ordered by creation time and ID.
One important caution
If the sort value is not unique and no unique tie-breaker exists, rows can disappear or repeat between pages.
PostgreSQL — Queries — PostgreSQL Global Development Group