The Software Herald
  • Home
No Result
View All Result
  • AI
  • CRM
  • Marketing
  • Security
  • Tutorials
  • Productivity
    • Accounting
    • Automation
    • Communication
  • Web
    • Design
    • Web Hosting
    • WordPress
  • Dev
The Software Herald
  • Home
No Result
View All Result
The Software Herald

GraphQL Pagination: Relay Cursor vs Offset for Live Infinite Scroll

Don Emmerson by Don Emmerson
April 5, 2026
in Dev
A A
GraphQL Pagination: Relay Cursor vs Offset for Live Infinite Scroll
Share on FacebookShare on Twitter

Cursor-based pagination vs offset-based pagination: choosing the right pagination for reliable infinite scroll

Cursor-based pagination and offset-based pagination explained: how each works, their trade-offs, and which to use for live feeds and infinite scroll today.

Why pagination matters for infinite scroll and virtualization

Related Post

PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle

PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle

April 11, 2026
CSS3: Tarihçesi, Gelişimi ve Modern Web Tasarımdaki Etkisi

CSS3: Tarihçesi, Gelişimi ve Modern Web Tasarımdaki Etkisi

April 11, 2026
Fluv: 20KB Semantic Motion Engine for DOM-First Web Animation

Fluv: 20KB Semantic Motion Engine for DOM-First Web Animation

April 10, 2026
VoxAgent: Local-First Voice Agent Architecture, Safety and Fallbacks

VoxAgent: Local-First Voice Agent Architecture, Safety and Fallbacks

April 10, 2026

Pagination is the mechanism APIs use to return large datasets in manageable chunks instead of sending every record at once. When a frontend implements infinite scroll with virtualization, the choice between offset-based pagination and cursor-based pagination is a production decision that affects correctness and user experience. Cursor-based pagination and offset-based pagination approach the same problem in fundamentally different ways, and that distinction determines whether a feed will show duplicate items, accidentally skip entries, or support jumping to arbitrary pages.

How offset-based pagination works

Offset-based pagination asks the server to skip a fixed number of positions and return the next block of items—typically via query arguments named offset and limit. On the server this is often implemented as a simple slice operation: return the items located between offset and offset + limit. The client tracks how many items it has and increments the offset by the page size for each fetch. Servers commonly return a total count so the client can decide when there are no more pages left.

Cases where offset looks attractive

Offset is simple to implement and easy to reason about. It is useful when the data is largely static (for example, a dealer locator, a product catalog, or search results) and when the UI needs to let users jump directly to page N, because offset arithmetic maps directly to page numbers. If the underlying list does not change while a user is paging, offset’s positional model behaves exactly as intended.

Why offset breaks on live data: skipped items

Offset treats the list as indexed positions rather than concrete items. If items are deleted while a user is paging, the list “shrinks” and positions shift. In that scenario the server will skip the next N positions based on the stale offset, and an item that slid up into the window between requests can be skipped entirely—never shown to the client. This is the skipped-item problem: offset skips items when the list changes shape during pagination.

Why offset breaks on live data: duplicate items

The opposite pathology happens when new items are inserted at the head of a feed (for example, a newsfeed or a timeline where new posts arrive at the top). Because offset always means “skip N positions,” new items push previously seen items down by one or more positions. When the client requests the next page using the old offset, the server will return items that occupy those positions now, which can include items the client has already seen. The result is visible duplicate items in the client’s list. Both duplication and skipping come from the same root cause: offset answers “skip N slots,” not “skip these specific items.”

What cursor-based pagination is and how it differs

Cursor-based pagination replaces positional skipping with a data-anchored bookmark. Rather than saying “skip 40 items,” the client says “give me the items after this specific item.” The server supplies a cursor with each item—a pointer that identifies that item’s position in the ordering. On the subsequent request the client sends the last received cursor back (often as an after parameter) and asks for the next N items after that cursor. The server locates the item the cursor represents and returns the next block relative to that item, not relative to an abstract index.

Why cursors avoid duplicates and skips

Because a cursor references a concrete item (for example, a timestamp or an encoded identifier), it serves as an anchor even when the list grows or shrinks. If new posts are added at the top of the feed, the cursor still points to the last item the client saw and the server will return everything after that item—so nothing is duplicated. If the item identified by the cursor is deleted, cursors based on timestamps or similar values still work: the server can return items created before or after the timestamp. In short, the cursor bookmarks data rather than positions, which makes pagination stable under inserts and deletes.

Opaque cursors: encoding and rationale

Cursors are commonly encoded (for example, base64) so they appear opaque to clients. Encoding serves three purposes. First, it abstracts implementation details: the client does not need to understand whether the cursor encodes an ID, a timestamp, or another internal value. Second, it reduces the temptation for clients to construct cursors manually or to infer internal database row IDs, which has security and correctness implications. Third, it gives the server flexibility to change the cursor’s internal representation without breaking clients that treat the cursor as a black box.

The trade-off: no arbitrary page jumps with cursors

The price of cursor stability is sequentiality: cursor-based pagination is designed to move forward (or backward) from a known cursor. There is no simple arithmetic that maps a page number to a cursor, so a UI that needs a “jump to page 10” control cannot do that without first obtaining the cursor that corresponds to the start of page 10—typically by iterating through the preceding pages. Offset pagination retains the ability to jump arbitrarily via offset = (page – 1) * limit.

Relay’s pagination model and GraphQL conventions

Facebook’s Relay specification formalized cursor-based pagination for GraphQL. Relay introduced a consistent structure that many GraphQL ecosystems reference: the Connection (the whole paginated list), Edge (an individual item bundled with its cursor), and Node (the data item inside an Edge). Along with those concepts, Relay defined PageInfo fields such as endCursor, startCursor, hasNextPage, and hasPreviousPage. A Relay-style API returns edges—each with its own cursor—so clients can begin pagination from any returned item, not only the last one. This per-item cursor model also simplifies cache merges and list reconciliation on the client.

Client-side tooling: cache policies and built-in helpers

Some GraphQL clients supply helpers that understand Relay-style pagination. For example, a GraphQL client can expose a relayStylePagination helper that knows how to merge paginated responses automatically into a single cached list. Offset-based pagination, by contrast, often requires manual cache merge logic because the client must reconcile items fetched by index rather than by cursor. That implementation difference is one reason teams sometimes adopt Relay-style conventions even if they don’t use Relay itself.

Concrete guidelines for choosing between cursor and offset

A single question often resolves the choice: does new data appear at the top of the list while users are actively scrolling? If yes—examples include social feeds, notifications, and chat messages—cursor-based pagination is the safer option because it avoids duplicates and skipped items caused by concurrent inserts and deletes. If no—examples include dealer directories, relatively static product catalogs, and stable search results—offset-based pagination remains a pragmatic, simpler choice. The most common mistake in practice is adding cursor complexity to lists that do not require it.

Developer implications: implementation complexity and maintenance

Offset pagination is conceptually straightforward and fast to implement: slice operations and offset arithmetic are easy to reason about. Cursor pagination requires designing a cursor encoding, ensuring the server can resolve cursors reliably (for example, via timestamps or encoded IDs), and updating cache policies on the client. Relay-style pagination adds an additional convention—edges and pageInfo—that a server and client must agree on. That extra complexity can be worthwhile for live data, but it is unnecessary overhead for static datasets.

Business and product implications

At the product level, the pagination choice affects perceived quality and user trust. A newsfeed that shows the same story twice or silently skips items undermines trust and feels buggy; cursor-based pagination prevents those experiences when the feed is live. On the other hand, a commerce catalog that enables users to jump to page 12 should favor offset for usability, because business workflows and discovery patterns often rely on predictable page numbers. Teams should align the technical decision with the product’s interaction patterns and data volatility.

Operational considerations and caching

Cursor-based pagination pairs well with server-side queries that can locate items by timestamp or by decoded cursor value, and it tolerates deletions because time-anchored cursors still represent a meaningful boundary. Offset-based pagination is simple to cache and to compute in many database-backed systems, but caches must account for the fact that inserts and deletes change the meaning of offsets. Client-side caches that merge offset pages need explicit merge strategies; Relay-style caches can rely on per-edge cursors to perform safer merges.

When hybrid approaches make sense

There are scenarios where teams use a pragmatic mix: offset-based pagination for parts of an application where page jumping is required and data is stable, and cursor-based pagination for feeds that receive frequent updates. Choosing a hybrid approach requires clear API documentation and client-side handling that selects the right strategy per endpoint, avoiding accidental mixing that would produce inconsistent UX.

Broader implications for frontend engineering and data fetching

Understanding the offset-versus-cursor distinction changes how engineers think about stateful data fetching. It reframes pagination as a question of how clients remember "where they were"—by position or by item—rather than a purely presentation concern. That shift has ripple effects: cache design, API ergonomics, telemetry, and error handling all depend on whether a client expects idempotent, position-based navigation or resilient, data-anchored continuation. For developer tooling, standardized shapes such as Relay’s Connection/Edge/Node help reduce cognitive load across teams and make it easier to reason about list merges, optimistic updates, and pagination boundaries.

New and existing systems also need to consider operational edge cases: what happens when the cursor-anchored item is removed, how to encode cursors safely, and how client and server clocks or ordering guarantees affect cursor semantics (for example, timestamp-based cursors assume a consistent sort order). These are practical engineering constraints that dictate whether a given cursor format will behave robustly in production.

A deliberate choice between offset and cursor pagination also aligns with business priorities: if fast implementability and page jumping are more important than handling live inserts, offset is often the correct trade-off; if data is actively mutating during user sessions, the stability of cursors outweighs the inability to jump arbitrarily.

Future developments in API design and client frameworks may further blur these lines by offering higher-level primitives that encapsulate cursor semantics while providing "page-like" navigation experiences. For now, the practical rule is straightforward: prefer offset for static or jump-oriented scenarios, and prefer cursors for live, fast-changing feeds.

Looking ahead, expect pagination decisions to remain a small but critical part of frontend architecture: as interfaces adopt more aggressive virtualization and as realtime updates become a default expectation, cursor semantics and robust caching policies will become increasingly central to delivering correct and predictable scroll experiences.

Tags: CursorGraphQLInfiniteLiveOffsetPaginationRelayScroll
Don Emmerson

Don Emmerson

Related Posts

PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle
Dev

PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle

by Don Emmerson
April 11, 2026
CSS3: Tarihçesi, Gelişimi ve Modern Web Tasarımdaki Etkisi
Dev

CSS3: Tarihçesi, Gelişimi ve Modern Web Tasarımdaki Etkisi

by Don Emmerson
April 11, 2026
Fluv: 20KB Semantic Motion Engine for DOM-First Web Animation
Dev

Fluv: 20KB Semantic Motion Engine for DOM-First Web Animation

by Don Emmerson
April 10, 2026
Next Post
Claude Code Auto-Memory: How It Manages Evolving Project Context

Claude Code Auto-Memory: How It Manages Evolving Project Context

Fedora Badges Revamp: React, Flask and MCP AI Integration

Fedora Badges Revamp: React, Flask and MCP AI Integration

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Rankaster.com
  • Trending
  • Comments
  • Latest
NYT Strands Answers for March 9, 2026: ENDEARMENTS Spangram & Hints

NYT Strands Answers for March 9, 2026: ENDEARMENTS Spangram & Hints

March 9, 2026
Android 2026: 10 Trends That Will Define Your Smartphone Experience

Android 2026: 10 Trends That Will Define Your Smartphone Experience

March 12, 2026
Best Productivity Apps 2026: Google Workspace, ChatGPT, Slack

Best Productivity Apps 2026: Google Workspace, ChatGPT, Slack

March 12, 2026
VeraCrypt External Drive Encryption: Step-by-Step Guide & Tips

VeraCrypt External Drive Encryption: Step-by-Step Guide & Tips

March 13, 2026
Minecraft Server Hosting: Best Providers, Ratings and Pricing

Minecraft Server Hosting: Best Providers, Ratings and Pricing

0
VPS Hosting: How to Choose vCPUs, RAM, Storage, OS, Uptime & Support

VPS Hosting: How to Choose vCPUs, RAM, Storage, OS, Uptime & Support

0
NYT Strands Answers for March 9, 2026: ENDEARMENTS Spangram & Hints

NYT Strands Answers for March 9, 2026: ENDEARMENTS Spangram & Hints

0
NYT Connections Answers (March 9, 2026): Hints and Bot Analysis

NYT Connections Answers (March 9, 2026): Hints and Bot Analysis

0
PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle

PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle

April 11, 2026
Constant Contact Pricing and Plans: Email Limits, Features, Trial

Constant Contact Pricing and Plans: Email Limits, Features, Trial

April 11, 2026
CSS3: Tarihçesi, Gelişimi ve Modern Web Tasarımdaki Etkisi

CSS3: Tarihçesi, Gelişimi ve Modern Web Tasarımdaki Etkisi

April 11, 2026
Campaign Monitor Pricing Guide: Which Plan Fits Your Email Volume?

Campaign Monitor Pricing Guide: Which Plan Fits Your Email Volume?

April 11, 2026

About

Software Herald, Software News, Reviews, and Insights That Matter.

Categories

  • AI
  • CRM
  • Design
  • Dev
  • Marketing
  • Productivity
  • Security
  • Tutorials
  • Web Hosting
  • Wordpress

Tags

Agent Agents Analysis API Apple Apps Architecture Automation build Cases Claude CLI Code Coding CRM Data Development Email Explained Features Gemini Google Guide Live LLM MCP Microsoft Nvidia Plans Power Practical Pricing Production Python RealTime Review Security StepbyStep Studio Systems Tools Web Windows WordPress Workflows

Recent Post

  • PySpark Join Strategies: When to Use Broadcast, Sort-Merge, Shuffle
  • Constant Contact Pricing and Plans: Email Limits, Features, Trial
  • Purchase Now
  • Features
  • Demo
  • Support

The Software Herald © 2026 All rights reserved.

No Result
View All Result
  • AI
  • CRM
  • Marketing
  • Security
  • Tutorials
  • Productivity
    • Accounting
    • Automation
    • Communication
  • Web
    • Design
    • Web Hosting
    • WordPress
  • Dev

The Software Herald © 2026 All rights reserved.