Skip to content

Intermediate · NoSQL, ORMs and data features · topic 29 of 54 · 25 min

Pagination: sending data page by page

Explanation

Pagination means sending a long list in small pages instead of all at once. The simple way uses LIMIT and OFFSET with a page number. For very big or fast-changing tables, cursor (keyset) pagination is faster: it asks for "the next 20 after this id".

Why paginate?

An online shop may have 2 lakh orders. Sending them all in one response would be slow for the database, use lots of server memory and burn the user's mobile data. Nobody reads 2 lakh rows anyway. So APIs return a small page, such as 20 items, and let the app ask for more.

Think of it like this: Pagination is like a thick exam result book printed in pages. You do not tear out all the pages to find your roll number; you open one page at a time, and the page number tells you where you are.

LIMIT and OFFSET

LIMIT says how many rows to return. OFFSET says how many rows to skip first. For page number page (starting at 1) and page size pageSize, the maths is: offset = (page - 1) * pageSize, and totalPages = ceil(total / pageSize).

sql
-- Page 3 with 10 items per page: skip 20, take 10
SELECT id, name, price
FROM products
ORDER BY id
LIMIT 10 OFFSET 20;
Offset pagination. ORDER BY makes the pages stable.
pagepageSizeOFFSETRows returned (of 45)
11001 to 10
2101011 to 20
5104041 to 45 (last page, only 5)
61050none
Careful: Always use ORDER BY on a unique column (or end with one, like ORDER BY price, id). Without it the database may return rows in any order, and the same item can appear on two pages while another is never shown.

Cursor (keyset) pagination

OFFSET has a hidden cost: for OFFSET 100000 the database still reads 100000 rows and throws them away. Deep pages get slower and slower. Keyset pagination remembers the last id the client saw and asks for rows after it. With an index on id, the database jumps straight there, so page 5000 is as fast as page 1.

sql
-- The client saw ids up to 1040 on the last page
SELECT id, name, price
FROM products
WHERE id > 1040
ORDER BY id
LIMIT 20;
Keyset pagination: WHERE id > last seen id. Uses the index, no rows thrown away.
Offset (page numbers)Cursor (keyset)
Jump to page 7EasyNot possible directly
Speed on deep pagesGets slowerStays fast
New rows added while scrollingItems can repeat or be skippedStable
Best forAdmin tables, search results with page numbersInfinite scroll feeds, big tables, APIs

What the response should include

json
// Offset style: GET /api/products?page=2&pageSize=20
{ "items": [ ... ], "page": 2, "pageSize": 20, "total": 134, "totalPages": 7 }

// Cursor style: GET /api/feed?limit=20&cursor=MTA0MA
{ "items": [ ... ], "nextCursor": "MTA2MA", "hasMore": true }
Send metadata so the app knows whether there is a next page.

The cursor is often the last id encoded as base64, so clients treat it as an opaque string and do not build their own. When there are no more rows, nextCursor is null.

Tip: Validate the query string: page must be a whole number of 1 or more, and pageSize should have a default (20) and a maximum (often 100). Otherwise someone sends pageSize=1000000 and your server falls over.

Watch the lesson

Pagination: sending data page by page · 1/6

Pagination

Big lists must be sent in small pieces. That is pagination.

Prefer a video by a teacher? Find free videos on “offset vs cursor pagination explained” on YouTube ↗

In real life: Infinite scroll on a shopping app

When you scroll the product list on a shopping app, the app first calls GET /api/products?limit=20. The backend returns 20 products and nextCursor. When you reach the bottom, the app sends the cursor back and gets the next 20. Even with lakhs of products and new ones added every minute, each call is fast and you never see the same product twice.

Practice (0/3 done)

Task 1 · Code · Javascript

Write paginate(items, page, pageSize) that returns { items, page, totalPages }. page starts at 1. items is the slice for that page. totalPages is Math.ceil(items.length / pageSize) (0 for an empty list). A page past the end returns an empty items array.

Task 2 · Code · SQL

A stationery shop lists products cheapest first, 3 per page. Write a query that returns page 2: the name and price of the 4th, 5th and 6th cheapest products. Use ORDER BY, LIMIT and OFFSET. Table: products(id, name, price).

Task 3 · Code · SQL

Keyset pagination: the app already showed orders up to id 6. Return the next 3 orders (id and amount) after id 6, in id order. Note the ids have gaps, so do not guess with OFFSET. Table: orders(id, amount).

Quick quiz

Question 1

1.With pageSize 20, what OFFSET gives page 4?

Question 2

2.There are 41 items and pageSize is 10. How many pages?

Question 3

3.Why is OFFSET 500000 slow?

Question 4

4.Which query is keyset (cursor) pagination?

Question 5

5.Why should an API cap pageSize (for example at 100)?

Read more (free)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

← Previous: ORMs: working with databases from code