0
0
GraphqlComparisonBeginner · 4 min read

Offset vs Cursor Pagination in GraphQL: Key Differences and Usage

In GraphQL, offset pagination uses page numbers or offsets to fetch data slices, while cursor pagination uses unique cursors to navigate through data. Cursor pagination is more reliable for dynamic data and large datasets, avoiding duplicates or missing items that offset pagination can cause.
⚖️

Quick Comparison

Here is a quick side-by-side comparison of offset and cursor pagination in GraphQL.

FactorOffset PaginationCursor Pagination
MethodUses numeric offset and limitUses unique cursor tokens
PerformanceCan be slower on large datasetsEfficient for large or changing data
ReliabilityMay skip or duplicate items if data changesConsistent results despite data changes
ComplexitySimple to implementMore complex to implement
Use CaseSmall static datasets or simple appsLarge, dynamic datasets or real-time apps
⚖️

Key Differences

Offset pagination works by specifying a starting point (offset) and how many items to fetch (limit). It is easy to understand and implement but can cause problems when data changes between requests, leading to skipped or repeated items.

Cursor pagination uses a unique identifier (cursor) from the last fetched item to get the next set. This method handles data changes gracefully and is more efficient for large datasets because it avoids counting or skipping rows.

While offset pagination is straightforward, cursor pagination requires managing cursors and encoding/decoding them, which adds complexity but improves reliability and performance in many real-world GraphQL APIs.

⚖️

Code Comparison

Example of offset pagination in a GraphQL resolver fetching posts.

javascript
const resolvers = {
  Query: {
    posts: async (_, { offset = 0, limit = 10 }, { db }) => {
      return await db.post.findMany({
        skip: offset,
        take: limit,
        orderBy: { createdAt: 'desc' }
      });
    }
  }
};
Output
[{ id: 11, title: 'Post 11' }, { id: 10, title: 'Post 10' }, ..., { id: 2, title: 'Post 2' }]
↔️

Cursor Pagination Equivalent

Example of cursor pagination in a GraphQL resolver fetching posts.

javascript
const resolvers = {
  Query: {
    posts: async (_, { after, limit = 10 }, { db }) => {
      const cursorOptions = after ? { cursor: { id: after }, skip: 1 } : {};
      return await db.post.findMany({
        ...cursorOptions,
        take: limit,
        orderBy: { createdAt: 'desc' }
      });
    }
  }
};
Output
[{ id: 11, title: 'Post 11' }, { id: 10, title: 'Post 10' }, ..., { id: 2, title: 'Post 2' }]
🎯

When to Use Which

Choose offset pagination when your dataset is small, static, or when you need a simple implementation without complex cursor management. It works well for basic apps or admin panels.

Choose cursor pagination for large, frequently changing datasets or real-time applications where data consistency and performance matter. It prevents skipping or duplicating items and scales better with data growth.

Key Takeaways

Cursor pagination is more reliable and efficient for large or dynamic datasets in GraphQL.
Offset pagination is simpler but can cause data inconsistencies when data changes between requests.
Use offset pagination for small or static data and cursor pagination for scalable, real-time APIs.
Cursor pagination requires managing unique cursors, adding complexity but improving user experience.
Performance and data consistency are the main reasons to prefer cursor pagination over offset.