Cursor vs Offset Pagination in Frontend System Design
I am developer from India.
The Pagination Decision That Quietly Impacts Performance, UX, and Scalability
When developers hear the word pagination, most immediately think about databases.
LIMIT 10 OFFSET 20
Problem solved… right?
Not exactly.
In modern frontend systems, pagination is much more than splitting data into pages.
It directly affects:
Infinite scrolling
Rendering performance
API design
Caching strategy
Scroll restoration
Duplicate UI rendering
Real-time updates
Virtualization performance
And once you start building systems like:
Instagram feeds
LinkedIn timelines
Chat applications
Notification systems
Infinite scroll UIs
pagination suddenly becomes a Frontend System Design problem.
The two most common approaches are:
Offset-Based Pagination
Cursor-Based Pagination
Let’s deeply understand both from a frontend engineering perspective.
Why Pagination Matters in Frontend Systems
Imagine rendering 1 million posts at once.
Your application would suffer from:
Huge API payloads
Slow rendering
Memory pressure
UI freezes
Poor mobile performance
Increased Time to Interactive (TTI)
Instead, frontend systems load data incrementally.
That’s where pagination comes in.
Offset Pagination
Offset pagination is the traditional page-based approach.
Example:
GET /products?page=3&limit=10
Backend internally calculates:
offset = (page - 1) * limit
Database query:
SELECT * FROM products
LIMIT 10 OFFSET 20;
Real-World Example: E-Commerce Product Listing
Offset pagination works beautifully for:
Amazon product listings
Admin dashboards
Analytics tables
CRM systems
Because users expect:
Page 1 2 3 4 5 ... 100
This UX naturally maps to offset pagination.
Why Frontend Developers Like Offset Pagination
1. Simple State Management
Frontend only stores:
currentPage = 5
Easy to manage.
2. Easy API Design
Simple query params:
?page=5
3. Easy Caching
Libraries like React Query work nicely:
useQuery(["products", page], fetchProducts)
4. Supports Jump Navigation
Users can directly visit:
?page=50
This is extremely useful in:
Reporting systems
Admin panels
Large tables
The Hidden Frontend Problem With Offset Pagination
Offset pagination starts breaking down in dynamic systems.
Imagine a social media feed.
You fetch:
Post A
Post B
Post C
Meanwhile, new posts arrive.
Now the order shifts.
Your next request may suddenly return:
Post C again
or skip some posts entirely.
Duplicate Rendering Problem
This is one of the most common infinite scroll bugs.
Example:
Initial data:
1 2 3 4 5
New item inserted:
0 1 2 3 4 5
Second request:
OFFSET 5 LIMIT 5
Result:
5 6 7 8 9
Now the frontend sees:
5
twice.
This creates:
Duplicate cards
Broken infinite scroll
Flickering UI
Incorrect virtualization behavior
Why Infinite Scroll Changes the Architecture
Modern applications heavily rely on infinite scrolling.
Examples:
Instagram
LinkedIn
Reddit
TikTok
YouTube
Infinite scrolling requires:
Stable ordering
Continuous loading
Smooth merging
Consistent rendering
Offset pagination struggles in these scenarios.
Cursor Pagination
Cursor pagination works differently.
Instead of saying:
"Skip 20 rows"
it says:
"Continue after this item."
Example:
GET /feed?cursor=abc123
Frontend stores:
nextCursor
instead of page numbers.
Real-World Analogy
Offset Pagination
"Start from the beginning and count."
Cursor Pagination
"Continue from where we stopped."
That single difference changes scalability massively.
Typical Cursor API Response
{
"data": [...],
"nextCursor": "eyJpZCI6MTAxfQ==",
"hasMore": true
}
Frontend stores:
nextCursor
and uses it for the next request.
Why Cursor Pagination Works Better for Frontend Feeds
Feeds constantly change.
New content keeps arriving.
Cursor pagination provides:
Stable ordering
Better merging
Fewer duplicates
Smoother scrolling
Better real-time behavior
This is why most large-scale social platforms prefer cursor pagination.
Infinite Scroll Flow in Frontend
Step 1: Initial Fetch
GET /feed
Response:
{
"posts": [...],
"nextCursor": "abc"
}
Step 2: User Scrolls
Frontend detects bottom reach.
loadMore()
Step 3: Next Request
GET /feed?cursor=abc
Step 4: Merge Data
setPosts(prev => [...prev, ...newPosts])
This architecture scales much better.
React Query Example
Cursor pagination naturally fits infinite queries.
useInfiniteQuery({
queryKey: ["feed"],
queryFn: fetchFeed,
getNextPageParam: lastPage => lastPage.nextCursor
})
This pattern is extremely common in production systems.
Why Cursor Pagination Helps Virtualization
Large feeds often use virtualization libraries like:
react-window
react-virtualized
FlashList (React Native)
These libraries require stable item ordering.
Offset pagination can reorder items unexpectedly.
Cursor pagination maintains consistency better.
Real Systems That Use Cursor Pagination
Social Feeds
Instagram
Twitter/X
Facebook
LinkedIn
Chat Applications
WhatsApp
Slack
Discord
Messages arrive continuously.
Stable pagination is mandatory.
Notifications
Notifications are highly dynamic.
Cursor pagination prevents missing or duplicate notifications.
Systems Where Offset Pagination Still Wins
Cursor pagination is not always the answer.
Offset pagination is still perfect for:
Admin dashboards
Analytics tables
Employee directories
Product catalogs
Search result pages
Because users expect:
Page 1 of 500
Frontend Tradeoff Summary
| Problem | Offset Pagination | Cursor Pagination |
|---|---|---|
| Infinite Scroll | Weak | Excellent |
| Jump to Page | Excellent | Difficult |
| Real-Time Data | Weak | Excellent |
| Duplicate Prevention | Weak | Strong |
| Simple Tables | Excellent | Overkill |
| Large Feeds | Poor | Excellent |
| Implementation Simplicity | Easy | Medium |
A Practical Rule of Thumb
Use Offset Pagination When:
You are building:
Dashboards
Reporting tools
Admin portals
Product listings
Search pages
Use Cursor Pagination When:
You are building:
Social feeds
Chat systems
Activity timelines
Infinite scroll UIs
Notification systems
The Most Important Frontend Insight
Pagination is not just a backend concern.
It impacts:
Rendering architecture
UX smoothness
API contracts
State management
Virtualization
Real-time synchronization
This is why pagination becomes a Frontend System Design decision, not just a database implementation detail.
Final Thoughts
Offset pagination is simple and great for structured navigation.
Cursor pagination is scalable and ideal for dynamic applications.
As frontend systems increasingly move toward:
Infinite scroll
Real-time updates
Massive feeds
Live synchronization
cursor pagination becomes increasingly important.
If you’re preparing for:
Frontend system design interviews
Senior frontend roles
Large-scale React applications
understanding this tradeoff deeply is extremely valuable.
Because in modern frontend engineering:
UX scalability matters just as much as backend scalability.


