Databases 6 min read

Why OFFSET/LIMIT Pagination Breaks at Scale and How to Use High‑Performance Keyset Pagination

The article explains why traditional OFFSET and LIMIT pagination becomes inefficient for large tables due to full‑table scans, demonstrates the performance gap with real‑world examples, and presents keyset (cursor‑based) pagination as a fast, index‑driven alternative with practical query patterns.

IT Architects Alliance
IT Architects Alliance
IT Architects Alliance
Why OFFSET/LIMIT Pagination Breaks at Scale and How to Use High‑Performance Keyset Pagination

Background

Modern APIs that expose large data sets need pagination that scales. While OFFSET + LIMIT works for small tables, it becomes a performance bottleneck as the number of rows grows beyond what fits in memory.

Problem with OFFSET + LIMIT

When the offset is large the database must read every row up to the offset, causing a full‑table scan, heavy disk I/O, and unnecessary memory consumption. For example, the query

SELECT * FROM users ORDER BY id LIMIT 20 OFFSET 500000;

on a table of 100 million rows forces the engine to scan the first 500 000 rows before returning just 20 rows.

A benchmark on a 100 k‑row test table shows the OFFSET/LIMIT version taking more than 30 × longer than an optimized approach.

Live comparison: https://www.db-fiddle.com/f/3JSpBxVgcqL3W2AzfRNCyq/1?ref=hackernoon.com

Proof‑of‑concept repository: https://github.com/IvoPereira/Efficient-Pagination-SQL-PoC?ref=hackernoon.com

Keyset (Cursor‑Based) Pagination

Instead of an offset, store the last seen primary‑key (or a unique timestamp) and request rows greater than that value. This lets the database use the primary‑key index directly, avoiding scans outside the desired range.

SELECT * FROM users
WHERE id > :last_id
ORDER BY id
LIMIT 20;

Benchmarking the same dataset shows execution time dropping from ~12.80 seconds to ~0.01 seconds.

Illustration of the original slow query versus the optimized keyset query:

Key requirements for keyset pagination:

A unique, monotonic column (e.g., auto‑increment integer ID, UUID, or timestamp) must exist.

If such a column is missing, adding an auto‑increment primary key solely for pagination is recommended.

Caveats:

Keyset pagination cannot jump directly to an arbitrary page number without knowing the corresponding key value.

It is ideal for “next”/“previous” navigation patterns rather than random page access.

Further Reading

In‑depth discussion of list pagination techniques: http://mysql.rjweb.org/doc.php/lists

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceSQLDatabase OptimizationpaginationKeyset PaginationOFFSET LIMIT
IT Architects Alliance
Written by

IT Architects Alliance

Discussion and exchange on system, internet, large‑scale distributed, high‑availability, and high‑performance architectures, as well as big data, machine learning, AI, and architecture adjustments with internet technologies. Includes real‑world large‑scale architecture case studies. Open to architects who have ideas and enjoy sharing.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.