System Design

API Pagination at Scale: Why OFFSET 100,000 is a Database Killer

Learn the technical difference between Offset-based and Cursor-based pagination. Master the Keyset pagination pattern for high-performance APIs.

Sachin Sarawgi·April 20, 2026·2 min read
#api-design#pagination#sql#performance#database-optimization

API Pagination at Scale: Moving Beyond OFFSET

Designing a paginated API seems simple: just use LIMIT 20 OFFSET 100. This works perfectly for the first few pages. However, once your users reach page 5,000, your database performance will fall off a cliff.

1. The Problem with OFFSET

When you execute OFFSET 100,000, the database doesn't magically jump to the 100,000th row. It must:

  1. Scan the first 100,000 rows.
  2. Store them in memory to sort them.
  3. Discard the first 100,000 and return the next 20. The result: As the offset increases, the query gets linearly slower and more memory-intensive.

2. The Solution: Cursor-based Pagination (Keyset)

Instead of telling the database how many rows to skip, we tell it where we left off. This is Cursor-based Pagination (or Keyset Pagination).

  • How it works: We include a unique, ordered value (like id or created_at) in the API response as a "cursor."
  • The Query:
-- Using the ID of the last item on the previous page
SELECT * FROM orders 
WHERE id > 54321 
ORDER BY id ASC 
LIMIT 20;

The Benefit: The database uses an index to jump directly to the specific row in $O(\log N)$ time, regardless of how deep the user is in the dataset.

3. Dealing with Complex Sorts

If you need to sort by something non-unique (like price), you must use a Tie-breaker.

  • The Cursor: (price, id).
  • The Query:
SELECT * FROM products 
WHERE (price, id) > (19.99, 101) 
ORDER BY price ASC, id ASC 
LIMIT 20;

4. When to use OFFSET?

Offset-based pagination is only acceptable if:

  1. Your dataset is small (a few thousand rows).
  2. You must support jumping to a specific page number (e.g., "Go to page 45").
  3. Data consistency across pages is not a concern (Offset pagination skips/duplicates items if new rows are inserted during a scroll).

Summary

For high-scale APIs, OFFSET is a debt. It leads to slow queries and inconsistent results. By switching to Cursor-based pagination, you provide sub-millisecond page loads for your users, even if they are browsing a list of 100 million items.


Next: Database Sharding vs. Partitioning: High Scale Strategies Previous: Distributed Caching at Scale: Thundering Herd Strategies

📚

Recommended Resources

Designing Data-Intensive ApplicationsBest Seller

The definitive guide to building scalable, reliable distributed systems by Martin Kleppmann.

View on Amazon
Kafka: The Definitive GuideEditor's Pick

Real-time data and stream processing by Confluent engineers.

View on Amazon
Apache Kafka Series on Udemy

Hands-on Kafka course covering producers, consumers, Kafka Streams, and Connect.

View Course

Practical engineering notes

Get the next backend guide in your inbox

One useful note when a new deep dive is published: system design tradeoffs, Java production lessons, Kafka debugging, database patterns, and AI infrastructure.

No spam. Just practical notes you can use at work.

Sachin Sarawgi

Written by

Sachin Sarawgi

Engineering Manager and backend engineer with 10+ years building distributed systems across fintech, enterprise SaaS, and startups. CodeSprintPro is where I write practical guides on system design, Java, Kafka, databases, AI infrastructure, and production reliability.

Found this useful? Share it: