APIs often return data in bulk—be it products, transactions, logs, or posts. However, returning all records in one go can be disastrous for performance and usability. That's where API Pagination comes in.
In this blog, we’ll explore what pagination is, why it matters, the common strategies (with pros, cons, and examples) and best practices for implementation.
🚨 The Problem: Large Data Sets
Imagine an e-commerce app retrieving 1 million products or a social platform loading 10 years of user activity at once. Returning such massive datasets:
- Increases memory and CPU usage on the server
- Slows down API response time
- Causes timeouts or crashes on the client
- Eats up network bandwidth unnecessarily
Pagination helps mitigate this by allowing the client to fetch data in manageable chunks.
📦 Common Use Cases
- Infinite scrolling (e.g., Twitter feed)
- Search results (e.g., e-commerce filters)
- Log viewers (e.g., admin dashboards)
- Reports and analytics over large time spans
🧭 How Clients Specify Data Chunks
Clients typically specify:
- Page size: Number of items per page (e.g., 10, 50, 100)
- Page or offset: Which chunk of data they want (e.g., page 3 or offset 100)
- Cursor or key: A unique pointer to continue from where the last call ended
⚙️ Pagination Methods: Pros, Cons & Complexity
1. Offset & Limit Pagination
Description:
Client provides a numeric offset
(start index) and limit
(number of records).
Example:
GET /products?offset=100&limit=20
Pros:
- Simple to implement
- Easy for clients to understand
Cons:
- Expensive for large offsets (e.g., offset=100000)
- Data inconsistencies if new records are added or removed during paging
Complexity:
🔹 Low (but O(N)
DB scan for large offsets)
2. Page-Based Pagination
Description:
Uses page
and pageSize
instead of numeric offsets.
Example:
GET /products?page=5&pageSize=50
Pros:
- Human-readable page numbers
- Works well for small, stable datasets
Cons:
- Suffers from same issues as offset-based (performance & consistency)
Complexity:
🔹 Low
3. Cursor-Based Pagination (a.k.a. Seek Pagination)
Description:
Uses a unique, immutable field (e.g., id
, createdAt
) to fetch the next set.
Example:
GET /messages?cursor=8756&limit=20
Pros:
- Efficient for large datasets
- Consistent even with concurrent updates
Cons:
- Harder to implement and debug
- Requires indexed and sortable fields
Complexity:
🔸 Medium to High
4. Time-Based Pagination
Description:
Fetches records created before/after a certain timestamp.
Example:
GET /logs?start=2025-01-01T00:00:00Z&end=2025-01-02T00:00:00Z
Pros:
- Great for time-series data (logs, events)
- Easy to cache and archive
Cons:
- Can miss or duplicate records with identical timestamps
Complexity:
🔸 Medium
5. Keyset Pagination
Description:
Uses sorted, indexed keys (e.g., id
) to get the next page.
Example:
GET /orders?after_id=1050&limit=20
Pros:
- High performance for deep pagination
- Resilient to data changes
Cons:
- Doesn’t allow jumping to arbitrary pages
- Can’t handle unsorted or composite keys easily
Complexity:
🔸 Medium
6. Hybrid Pagination
Description:
Combines techniques like offset + cursor or cursor + timestamp.
Example:
GET /comments?after=1000&createdBefore=2025-01-01&limit=50
Pros:
- Flexible and powerful
- Can balance performance with UX needs
Cons:
- Most complex to implement
- Can confuse API consumers
Complexity:
🔶 High
🛠 Best Practices for Implementing Pagination
- Use default limits: Always cap the number of records returned (
limit=100
max). - Return metadata: Include fields like
totalCount
,nextPage
,hasMore
, ornextCursor
in the response. - Document your API: Clearly explain supported pagination styles in your API docs.
- Index your sort fields: Especially for cursor or keyset pagination.
- Avoid offset for large data: Cursor/keyset is better for scale and consistency.
- Consistent sorting: Always sort by a unique, stable column (e.g.,
id
,createdAt
) to prevent duplicates or missing data. - Make pagination optional: But enforce it with sane defaults if not specified.
🧠 Conclusion
Pagination isn’t just about breaking data into pages—it’s about balancing performance, usability, and consistency.
Method | Use When | Scale | Complexity |
---|---|---|---|
Offset & Limit | Small datasets, admin UI | ❌ Poor | 🔹 Low |
Page-Based | User-friendly UX | ❌ Poor | 🔹 Low |
Cursor-Based | Large lists, scrolling | ✅ High | 🔸 Med-High |
Time-Based | Logs, metrics | ✅ Medium | 🔸 Medium |
Keyset | Large ordered data | ✅ High | 🔸 Medium |
Hybrid | Complex/UX + performance | ✅ High | 🔶 High |
Choose wisely based on your use case, and always test performance at scale.
Top comments (0)