Call limit

The GraphQL Admin API's limits are based on a calculated cost for each individual query. This is in contrast to the Admin API, which limits an API client's requests based on the number of requests made over a set period of time.

Cost calculation

Every field in the schema has an integer cost value assigned to it. The cost of a query is the sum of the costs of each field.

Requested and actual cost

Shopify calculates the cost of a query both before and after query execution. The requested cost is based on the number of fields requested. The actual cost is based on the results returned, since the query can end early due to an object type field returning null, or connection fields can return fewer edges than requested.

Single query limit

A single query to the API cannot exceed a cost of 1000. This limit is enforced before query execution begins, and is therefore based on the requested cost of the query rather than the actual cost.

Leaky bucket rate limit

The leaky bucket rate limit functions like the Admin API's rate limiting system, but considers the cost of requests over time, rather than the number of requests. An app is given a bucket of 1000 cost points, with a leak rate of 50 cost points per second. This means that the total cost of your queries cannot exceed 1000 points at any given time, and that room is created in the app's bucket at a rate of 50 points per second. By making simpler, low-cost queries, you can make more queries over time.

The limit uses a combination of the requested and the actual query cost. Before execution can begin, the app’s bucket must have enough room for the requested cost of the query; then, once execution is complete, the bucket is refunded the difference between the requested cost and the actual cost of the query.

Determining query cost

The query response includes information about the cost of the query, and the state of the throttle under the extensions key:

"extensions": {
  "cost": {
    "requestedQueryCost": 101,
    "actualQueryCost": 46,
    "throttleStatus": {
      "maximumAvailable": 1000,
      "currentlyAvailable": 954,
      "restoreRate": 50
    }
  }
}

To get a detailed breakdown of how each field contributes to the requested cost, you can make your query with the X-GraphQL-Cost-Include-Fields header set to true:

"extensions": {
  "cost": {
    "requestedQueryCost": 101,
    "actualQueryCost": 46,
    "throttleStatus": ...,
    "fields": [
      {
        "path": [
          "shop"
        ],
        "definedCost": 1,
        "requestedTotalCost": 101,
        "requestedChildrenCost": 100
      },
      ...
    ]
  }
}

Sign up for a Partner account to get started.

Sign up