Pagination: Offset vs Cursor-Based

Medium

Offset

Page + limit style

  • - Simple mental model
  • - Degrades on large offsets

Cursor

Token-based traversal

  • - Stable under inserts
  • - More complex client logic

Consistency

Avoid duplicates/gaps

  • - Stable sort key required
  • - Handle stale cursors

UX

Infinite scroll vs pages

  • - Context retention
  • - Back-navigation strategy

Core Lens

Use offset for simple stable lists; use cursor when data mutates frequently or scale grows.

Flow

Query
Page boundary
Consistency check
Next page token

Choosing the right pagination strategy for performance, consistency, and UX in real frontend systems.

Rule of thumb: Use offset for stable, page-number UIs. Use cursor for feeds and infinite scroll with frequent inserts/deletes.

Offset-Based Pagination

Offset asks the server for items starting at a numeric position.

GET /api/posts?page=3&limit=20
GET /api/posts?offset=40&limit=20

Advantages

  • Simple and fast to implement
  • Easy “Go to page N” support
  • Usually returns total pages/count
  • Good for admin tables and static lists

Disadvantages

  • Deep offsets can be slower at scale
  • Records may shift when new data is inserted
  • Can show duplicates or skip items in live feeds

Cursor-Based Pagination

Cursor uses a pointer from the last item in the current result set.

GET /api/posts?limit=20
GET /api/posts?cursor=eyJjcmVhdGVkQXQiOiIyMDI2LTAyLTIzVDEwOjAwOjAwWiIsImlkIjoiNDEyIn0=&limit=20
{
  "items": [/* 20 posts */],
  "pageInfo": {
    "nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTAyLTIzVDA5OjU5OjM4WiIsImlkIjoiMzkzIn0=",
    "hasMore": true
  }
}

Advantages

  • Stable ordering for changing datasets
  • Great for infinite scroll/timelines
  • More efficient for large datasets

Disadvantages

  • Hard to jump directly to page N
  • Requires deterministic sort keys
  • Total count is expensive / often omitted (can be stale on real-time feeds)

Backend Query Pattern

Offset SQL

SELECT id, created_at, title
FROM posts
ORDER BY created_at DESC, id DESC
LIMIT 20 OFFSET 400;

Cursor SQL (keyset pagination)

SELECT id, created_at, title
FROM posts
WHERE (created_at, id) < ($1, $2)
ORDER BY created_at DESC, id DESC
LIMIT 20;

Interview Answer Template

“For a live feed, I’d use cursor-based pagination with (createdAt, id) as the cursor key to avoid duplicates/skips while new items arrive. For an admin table where users jump to page 27, I’d use offset pagination.”

Mention one tradeoff and one mitigation:

  • Tradeoff: cursor can’t jump to arbitrary pages.
  • Mitigation: combine cursor for feed view with search/filter shortcuts and date-based anchors.