Shopify GraphQL: query cost and cursor pagination
A worked client model for Shopify’s query-cost budget and cursor pagination, showing why page position and request capacity are separate concerns.
- Query and cost budget
- Page and pageInfo
- Checkpoint and next cursor
Investigation question
Why can two successful GraphQL requests consume different capacity, and why is a page number not enough to resume a read? Shopify’s Admin GraphQL contract separates query cost from connection traversal. A reliable reader needs to track both.
Observed
Shopify documents cost-based limits for Admin GraphQL and distinguishes requested cost from actual cost. Query shape and selected fields matter; a request is not simply one interchangeable unit of capacity. The response can expose cost and throttle information that a client uses to plan subsequent work. Connections use cursor pagination. A reader requests a bounded set of results and uses pageInfo, including the continuation cursor and whether another page exists, to advance. The cursor is supplied by the API. It is not a numeric offset the client should invent or interpret as an internal row identifier.
Inferred
The client has two independent state variables: where to continue and when capacity permits another request. Increasing a page size may reduce request count while increasing the cost of each request. Selecting more nested fields may also change cost. Optimizing only for fewer HTTP calls can therefore be counterproductive. A saved cursor is a continuation token for a particular traversal. It should travel with the relevant query, filters and API version. Reusing it after changing the query shape without checking the contract would combine two different read plans.
Unknown & limitations
The analysis targets the cited Admin GraphQL baseline and public usage guides. It does not promise that a long traversal is a frozen snapshot while records change. Store plan limits, authorization scopes and field costs must be checked for the actual query and API version. No shop data, token, mutation or live rate-limit experiment was used.
Domain & data models
Illustrative cost calculation, not a published plan limit: if a response reports 120 currently available points and a proposed query requests 80, the client has enough reported capacity at that instant. If a later response reports only 30, blindly sending the same query is a different decision. A reader should use returned throttle information rather than a fixed sleep copied from another shop.
Workflows & state machines
A useful loop is: request one page; inspect data and GraphQL errors; record cost information; process the returned nodes; save the continuation cursor; then advance only when hasNextPage indicates more data. If the process stops after persisting the cursor but before persisting the page’s work, the next run may skip work. Checkpoint design is therefore part of correctness, separate from pagination syntax. A bounded verification would compare a small field selection with a wider one, inspect their reported costs, and traverse a known multi-page result while recording returned cursors. This is a proposed validation method, not a claim that this article ran against a shop.
API & protocol surfaces
The documented GraphQL read surface uses query selections and connections. Throttle metadata describes available query capacity; pageInfo describes position within a connection.