Definition
Imagine if every time you searched Google, it tried to load all 10 billion matching results at once. Your browser would crash, and you’d wait forever for nothing useful. Pagination solves this problem by breaking large result sets into smaller, digestible chunks - like serving a meal in courses rather than dumping everything on the table at once.
When an API has thousands or millions of records, sending them all in one response would be slow, waste bandwidth, and overwhelm the client application. Instead, pagination lets you request data in pages: “give me items 1-20” then “give me items 21-40” and so on. The server does less work per request, the network carries smaller payloads, and your app can display results immediately while users scroll for more.
There are several flavors of pagination, each with trade-offs. Offset-based pagination uses page numbers (page=2, limit=20) - simple but can miss or duplicate items if data changes between requests. Cursor-based pagination uses a pointer to the last item you saw - more reliable but you can’t jump to a specific page. The right choice depends on your data and how users interact with it. Social media feeds typically use cursors (infinite scroll), while search results often use offsets (page numbers).
Example
Pagination is everywhere, shaping how you consume information online:
Social Media Feeds: When you scroll through Instagram or Twitter/X, you’re experiencing cursor-based pagination. The app loads 20-30 posts, then as you approach the bottom, it fetches the next batch using the last post’s ID as a cursor. You never see page numbers because the feed is constantly changing - cursor pagination handles this gracefully.
E-commerce Search Results: When you search for “running shoes” on Amazon and see “Page 1 of 47”, that’s offset-based pagination. You can click to jump to page 10 directly. Amazon shows you exactly 48 items per page, and navigation links let you browse systematically through thousands of products.
Email Inbox: Gmail uses pagination to show your inbox in manageable chunks. The “Older” and “Newer” buttons move through your emails, and you can configure how many messages appear per page. Without pagination, loading a years-old inbox with 50,000 emails would be impossible.
Database Admin Panels: Tools like phpMyAdmin or Sequel Pro paginate database tables. When viewing a table with millions of rows, they show 30 rows at a time with controls to navigate. This prevents accidentally loading so much data that the tool freezes.
API Documentation Examples: Stripe’s API documentation shows paginated responses with has_more: true and a starting_after parameter. This teaches developers the pattern: request a page, check if there’s more, use the cursor to get the next batch.
Analogy
The Library Card Catalog (Digitized): Remember card catalogs? When searching for books about “history,” you wouldn’t get every card at once - you’d flip through a drawer, one section at a time. Pagination works the same way: you see a manageable batch, and controls let you move forward, backward, or jump to a specific section.
The Netflix Carousel: When you browse Netflix, you see a row of maybe 6-8 movie thumbnails with arrows to scroll left and right. Behind the scenes, Netflix doesn’t load every movie in that category - it loads a few at a time as you scroll. That’s pagination providing a smooth experience while conserving bandwidth.
The Restaurant Menu with Courses: A tasting menu at a fancy restaurant doesn’t bring all 12 courses at once. You get one course, enjoy it, then the next arrives when you’re ready. Pagination serves data the same way - in courses your application can handle and users can digest.
The Magazine Subscription: You don’t receive your entire year’s subscription of 12 magazines in one massive package. They arrive monthly - one issue at a time. Each magazine is like a “page” of your subscription, delivered when you’re ready for the next batch of content.
Code Example
// Offset-based pagination
GET /api/products?page=2&limit=20
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 157,
"totalPages": 8
},
"links": {
"first": "/api/products?page=1&limit=20",
"next": "/api/products?page=3&limit=20",
"last": "/api/products?page=8&limit=20"
}
}