Why you should consider using Relay connections for fetching large data sets

Last updated

Why using connections is a good idea?#

If you're integrating with Centra’s Integration API, and you're fetching lists of items (like products, orders, accounts, displays, etc.), there's one pattern you should be using consistently: connections, as defined by the Relay specification.

Connections offer a standardized, powerful way to paginate data, and they bring several concrete benefits that go beyond just fetching items in chunks.

With connections, you get access to the pageInfo object and a totalCount:

  • pageInfo.hasNextPage and pageInfo.endCursor make it easy to fetch the next set of results without guessing or hardcoding page numbers,
  • totalCount gives you an accurate count of all matching records, so you can build proper UI indicators or summaries when needed.

No more hand-rolled pagination logic – it’s all built in!

Stability and resilience during pagination#

With traditional page-based pagination, you might fetch page 1, then page 2 – but if the dataset changes in between (e.g., a new order is added, a product variant is deleted), you can end up skipping or duplicating items.

Connections use cursor-based pagination, which is far more resilient to these kinds of data changes. Cursors track the position in the dataset based on item identity and properties, not on shifting page offsets, so the result set remains consistent and stable as you paginate through it.

Example: fetching recent orders#

When you’re displaying a list of customer orders in your frontend (e.g., an admin dashboard or analytics view), you often want to paginate the data – showing a limited number of results per page, and letting users navigate using "Next" and "Previous" buttons.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 query pageOfOrders { orderConnection( where: {storeType: DIRECT_TO_CONSUMER} sort: [orderDate_DESC] first: 20 after: "b3JkZXJEYXRlOjIwMjUtMDYtMjUgMTc6NTA6MzA74oChwrbCpsO4O251bWJlcjoyMQ==" ) { totalCount pageInfo { hasNextPage endCursor # same as the cursor of the last edge } edges { cursor node { # order data is here id status orderDate grandTotal { formattedValue } } } } }

This query fetches a page of 20 recent orders (sort: [orderDate_DESC]) after a given cursor, which represents the last item fetched in the previous page. The connection returns both the data and everything needed to paginate efficiently. To fetch the next page, just put the endCursor into after. For a previous page, pass a before and last arguments instead of after and first.

You can even dynamically change the first value to fetch a different number of results per page – say, 10, 50, or 100 – depending on user preferences or other requirements.

Better performance#

Offset-based pagination (i.e., limit: 50, page: 10) often requires the backend to scan and count through hundreds or thousands of records to deliver the right subset. With cursors, the backend can efficiently seek directly to the next item, reducing query complexity and response time – especially in large datasets.

Cursor-based pagination is especially being optimized for sales data, which tends to grow indefinitely. In our testing we found that fetching hundreds or thousands of your orders and shipments can be an order of magnitude faster using connections compared to regular lists.