Deferring Query Response Data
Using the @defer directive
With GraphOS, your supergraph's router can defer returning data for certain fields in your schema. This enables a querying client to receive non-deferred data more quickly, because the router can return it immediately instead of waiting for all response data to be ready:
Both cloud supergraphs and self-hosted supergraphs support deferring fields with the router. Additionally, this feature is compatible with all supported subgraph libraries, because the logic resides entirely within the router!
How do I defer fields in a query?
ⓘ NOTE
Deferring query fields requires a defer-compatible client library. These libraries support receiving query data incrementally via multipart HTTP responses.
Defer support is currently available in Apollo Client for Web and Kotlin (experimental).
If you're using a defer-compatible client, you apply the @defer
directive to fragments in your queries to specify which fields you want to defer:
query GetTopProductsAndReviews {topProducts {idname# You always apply @defer to a fragment, not to individual fields... @defer {reviews {score}}}}
When your supergraph's router receives this query, it defers every field in these fragments that it's able to.
Which fields can my router defer?
Your supergraph's router can defer the following fields in your schema:
- Root fields of the
Query
type (along with their subfields) - Fields of any entity type (along with their subfields)
- Deferring entity fields is extremely powerful but requires some setup if you aren't using entities already. This is covered in more detail below.
See below for more information on each of these.
Query
fields
Your router can defer any field of your schema's Query
type, along with any subfields of those fields:
query GetUsersAndDeferProducts {users {id}... @defer {products {id}}}
With the query above, the router first returns a list of User
IDs, then later completes the response with a list of Product
IDs.
Entity fields
Your router supports deferring fields of the special object types in your supergraph called entities.
Entities are object types that often define their fields across multiple subgraphs (but they don't have to). You can identify an entity by its use of the @key
directive. In the example subgraph schemas below, the Product
type is an entity:
type Product @key(fields: "id") {id: ID!name: String!price: Int!}type Query {topProducts: [Product!]!}
type Product @key(fields: "id") {id: ID!reviews: [Review!]!}type Review {score: Int!}
Entities are query entry points into your subgraphs, and this is what enables your router to defer their fields: the router can send a followup query to a subgraph to fetch any entity fields that it doesn't fetch initially.
Here's an example query that defers entity fields using the subgraphs above:
query GetProductsAndDeferReviews {topProducts {idname... @defer {reviews {score}}}}
To handle this query, the router first resolves and returns a list of Product
objects with their IDs and names. Later, the router completes the response by returning review scores for each of those products.
ⓘ NOTE
It doesn't matter which subgraph defines a particular entity field! Queries can defer entity fields that are defined across any number of different subgraphs.
Defining entities in your subgraphs
If your subgraphs don't yet include any entities, you need to define some before clients can start deferring their fields in queries.
To learn about creating entities, see this article.
Requirements for @defer
To use @defer
successfully, your supergraph and its clients must meet the requirements listed below. These requirements are divided between general requirements (requirements for using @defer
at all) and entity-specific requirements (additional requirements for using @defer
with entity fields).
General requirements
- Clients must support receiving deferred query responses as multipart HTTP responses.
- This functionality is currently supported in Apollo Client for Web and Kotlin (experimental).
- Your supergraph must be one of:
- A cloud supergraph
- A self-hosted supergraph running the GraphOS Router
Entity-specific requirements
- Your subgraphs must each use a subgraph-compatible GraphQL server library.
- You must define one or more entities in your subgraph schemas.
- Each subgraph must define a reference resolver for each of its entities (or implement the corresponding functionality in your chosen subgraph library).
- This is what enables the router to directly access entity fields with followup sub-queries.