How to Implement Pagination in a REST API

Returning an entire dataset in a single API response doesn't scale — pagination breaks large result sets into manageable pages. This guide covers the common pagination approaches and how to choose between them.

Why Pagination Is Essential

Without pagination, an endpoint returning "all records" becomes progressively slower and more resource-intensive as your dataset grows, eventually becoming genuinely unusable — pagination is a foundational, not optional, API design consideration for any endpoint returning a list.

Offset-Based Pagination (Simplest, Most Common)

GET /api/products?limit=20&offset=40
SELECT * FROM products LIMIT 20 OFFSET 40;

Simple to implement and understand — but has a genuine performance problem at scale: a large offset requires the database to scan and discard many rows before reaching the requested page, becoming progressively slower for later pages.

Cursor-Based Pagination (Better for Large Datasets)

GET /api/products?limit=20&after=eyJpZCI6MTIzfQ==
SELECT * FROM products WHERE id > 123 ORDER BY id LIMIT 20;

Uses a reference point (often an encoded ID or timestamp) rather than a numeric offset — avoids the offset performance problem entirely, since the database can seek directly to the cursor position rather than scanning/discarding preceding rows.

Comparing the Two Approaches

ApproachProsCons
Offset-basedSimple, supports jumping to arbitrary page numbersSlow for large offsets, can show duplicates/gaps if data changes between requests
Cursor-basedConsistent performance at any scale, stable results even with concurrent data changesCan't jump to an arbitrary page number, slightly more complex to implement

Including Pagination Metadata in Responses

{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6MTQzfQ==",
    "has_more": true
  }
}

Include enough metadata for clients to easily request the next page without needing to construct cursor values themselves — a well-designed API returns the exact value/URL needed for the next request.

Setting Sensible Default and Maximum Page Sizes

const limit = Math.min(parseInt(req.query.limit) || 20, 100);

Provide a reasonable default (so clients don't need to always specify) and enforce a maximum (preventing a client from requesting an unreasonably large page that strains your server) — both important for API stability.

Documenting Your Pagination Approach

See How to Version an API Without Breaking Existing Clients and general API documentation practices — clearly document which pagination style your API uses and exactly how to use it, since inconsistent or undocumented pagination behavior is a common source of integration friction for API consumers.

Handling "Total Count" Requests Carefully

Providing a total record count alongside paginated results is convenient for clients but can itself be an expensive query on very large tables — consider whether an exact total is genuinely necessary, or whether an approximate/estimated count (or omitting it) is acceptable for your use case.

Common Errors

Duplicate or missing records when using offset pagination with frequently-changing data — a known limitation of offset-based pagination when the underlying dataset changes between page requests; cursor-based pagination is more resilient to this specific issue.

Continue Reading

Browse more articles in Object Storage, Messaging & APIs.

  • rest api pagination, cursor based pagination, offset vs cursor pagination, api pagination best practices
  • 0 أعضاء وجدوا هذه المقالة مفيدة
هل كانت المقالة مفيدة ؟

مقالات مشابهة

How to Set Up Self-Hosted S3-Compatible Object Storage with MinIO

MinIO is a high-performance, self-hosted object storage server compatible with the S3 API —...

How to Use Object Storage for Application File Uploads

Storing user-uploaded files directly on your application server's disk creates scaling and...

How to Install and Configure RabbitMQ on a VPS

RabbitMQ is a widely-used, robust message broker — enabling applications to communicate...

How to Install and Configure Redis as a Message Queue

Redis, primarily known as a cache, also works well as a lightweight message queue for simpler use...

How to Build and Secure a REST API on a VPS

This guide covers the essential security and architecture practices for deploying a REST API on...