Using the @defer directive
The @defer
directive allows clients to prioritize part of a GraphQL query without having to make more requests to fetch the remaining information. You can use this directive to minimize the overhead when fetching data from Shopify. Rather than maintaining multiple queries and performing several API calls, clients can make a single request and receive the data as a stream of responses.
Anchor to RequirementsRequirements
- Your app can make requests to the GraphQL Storefront API.
Anchor to Choosing a supported clientChoosing a supported client
The @defer
directive is currently a draft contribution to the GraphQL specification. To maximize compatibility with clients that support some variant of the @defer
specification today, we have implemented the spec as of its description on August 23, 2022.
You can use one of the following compatible GraphQL libraries:
The @defer
directive is not yet supported on Hydrogen.
Anchor to Optimize a query using ,[object Object]Optimize a query using @defer
@defer
The @defer
directive can be applied to fragment spreads and inline fragments in a GraphQL query. Fields cannot use @defer
directly.
Many client libraries support @defer
in two ways: after each response is received, or once all responses have been received. To get the benefits of @defer
it's strongly suggested to handle each response as it arrives, so the client can begin rendering as soon as possible.
The following example retrieves details about a product before the list of related products. It uses @defer
to deprioritize the productRecommendations
query, but still receive those recommendations afterward without making an additional request. Each response (including the undeferred part) begins with --graphql
.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL Response
Headers
Body
In the provided example, the @defer
directive is used with the relatedProducts
fragment. This fragment, defined separately, includes the productRecommendations
query. By using @defer
on this fragment, we're instructing to the server that it's acceptable to return the data for productRecommendations
after the product.
When the server processes this query, it first returns the main product data, indicated by the "hasNext": true
in the response. The server then continues to process the deferred fragment and returns the product recommendations. You will know that all parts have been received when the response contains "hasNext": false
.
There might be some situations where Shopify believes it to be more efficient to serve the deferred fragment inline, rather than as a second streamed value. In this case, the initial response will contain all of the requested JSON. As before, streamed responses are complete when indicated by the presence of "hasNext": false
in the response.
Anchor to Fetching carrier-calculated rates for the cart using ,[object Object]Fetching carrier-calculated rates for the cart using @defer
@defer
As of 2024-07, Cart#deliveryGroups
supports a new withCarrierRates
argument, used to indicate intent to fetch carrier-calculated rates. This capability requires mandatory use of @defer
directive to ensure that the calculation of the delivery rates does not delay the cart response.
When fetching the delivery groups using withCarrierRates: true
inside a @defer
fragment, the cart will initially calculate (excluding the delivery rates) and resolve the response, and then stream the fragment containing the rates once they're available.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL Response
Headers
Body
In the provided example, the first response fragment contains the non-deferred cart data, which is returned without delay from the pending carrier-calculated rates. Once the rates become available, the server returns the available delivery groups of the cart in the second fragment using the @defer protocol.
Fetching the carrier-calculated rates will not automatically select a delivery option. To select a carrier-calculated rate, please refer to cartSelectedDeliveryOptionsUpdate
. Furthermore, the cost
field is not updated when fetching of carrier-calculated rates.
Anchor to Technical detailsTechnical details
Streamed responses for @defer
follow the Incremental Delivery over HTTP specification for GraphQL. In particular, that means clients receive a multipart content response, indicated by the HTTP header of content-type: multipart/mixed; boundary=graphql
. If the client only supports a maximum of HTTP/1.1
, the response will also be served using transfer-encoding: chunked
, which is no longer necessary as of HTTP/2
.