Pagination is retrieving a long list in pieces instead of all at once. Two mechanisms dominate, and they fail differently.
Offset against cursor
| How you ask | Fails when | |
|---|---|---|
| Offset | "Skip 40, give me 20" | The list changes between calls — you get duplicates or gaps |
| Cursor | "Give me 20 after this token" | Rarely; the token pins your position |
Cursor pagination is the better design for anything that changes while you read it, which is every social feed. Offset pagination on a live feed will quietly show you the same post twice and miss another, with no error anywhere.
The clamped limit
Many APIs accept a limit parameter with a maximum. What happens when you exceed it is the interesting part:
?limit=100 on an API whose maximum is 40
clamped silently → returns 40, status 200
rejected → returns 400, "limit must be 1–40"
The first looks friendlier and is worse. A caller who asks for 100 and receives 40 concludes the account has 40 items. We refuse out-of-range limits with a 400 for exactly this reason — on the Mastodon posts route the range is 1–40, on the Bluesky posts route it is 1–100, and outside it you get an error rather than a number that means something other than what you asked.
No pagination at all
Some sources do not offer it. One platform's public page returns whatever posts happened to be in the document — measured across three accounts: 4, 5 and 10. There is no cursor, no limit parameter and no next page. The honest thing is to say so on the route's page rather than imply the list is complete.
Empty page or end of list?
These are different and should be distinguishable:
- End of list — you have everything. No cursor comes back.
- Empty result — this query matched nothing.
- Failed fetch — something broke.
An API that returns an empty array for all three leaves you unable to tell "done" from "broken". In our archive the equivalent distinction is kept in separate columns: a window that returned nothing is recorded differently from a window that errored, because a source that returns nothing has not failed.
Cost
On a per-resource price model, pagination is the cost — each item on each page is billable. Caching the identifiers you already have, rather than re-paginating to rediscover them, is usually the difference between an affordable job and an expensive one.