Fullstack GraphQL tutorial: @defer and Apollo GraphOS
Michael Watson
With Apollo GraphOS, you can improve your client app’s time-to-interactive (TTI) and reduce latency in a few lines of code. Just plug your GraphQL API into the supergraph and add the @defer
directive to the slow parts of your GraphQL query. When you mark slow fields with @defer
, the supergraph knows it can deliver those parts of the result asynchronously.
The @defer
directive is a proposal to the GraphQL specification that has been in development since July 2020. We know the GraphQL community has been eager to try it, so we announced full end-to-end support for @defer
across Apollo GraphOS at this year’s GraphQL Summit. Even if your GraphQL API doesn’t support @defer
yet, you can still use it with GraphOS.
In this tutorial, we’ll show you how to use @defer
with our e-commerce example. If you like what you see, you can follow the same steps to plug your GraphQL API into the supergraph and start using @defer
to craft a snappier user experience.
Get started with GraphOS
First, we need to connect our GraphQL API to GraphOS, Apollo’s supergraph platform. GraphOS includes a global supergraph runtime, powered by Apollo Router. It’s free to use with 10MM queries/month included. Create an account and add your GraphQL endpoint to set up your supergraph.
Here, we’re using https://hts-products-production.up.railway.app/ as our GraphQL endpoint. When we connect it to the supergraph, our GraphQL API becomes a subgraph.
Define our first entities
Now that we’re connected to the supergraph, let’s dive into our subgraph’s schema to define our first entities. An entity is a thing in the graph you can identify. Like a user with an account number, or a product in your catalog. You already have some entities in your schema today!
Why are entities important? Under the hood, the supergraph uses a query plan to determine how to fetch the deferred portions of a query. Apollo Federation builds that query plan with entities. Think of entities as the building blocks for the supergraph. We’re using them to power cool features coming soon to GraphOS, like live queries and caching.
To define your first entities:
- Install the Apollo Federation package for your subgraph. Ensure your schema is being built with the installed package.
- Add the
@key
directive to any type and define the key fields (typically theid
field). - Create the reference resolver for your entities.
Here are two examples showing how to add the @key
directive to a schema whether you’re using Schema Definition Language (SDL) or Code-first Schema Development:
Here are two examples showing how to add the reference resolver for the Product
entity we defined in step 2:
We’ve already completed those steps for you in our products subgraph schema and resolvers. Now try it in your graph! The more entities you define, the more places you can start using @defer
.
Remember that @defer
still works even if you have only one subgraph. A deferred query could be re-entrant within the same subgraph! 🤘
Add another subgraph
If you have several subgraphs, they can be added to a supergraph from the Subgraphs tab in GraphOS. While this step is optional, it’s a best practice to think about separation of concerns when designing your GraphQL schemas. We’ve already split our reviews entity into a separate subgraph for this example, but if you want to follow along, you can follow the instructions displayed in GraphOS and use the reviews deployment located at https://hts-reviews-production.up.railway.app/.
@defer
with Explorer
Test We’ve connected our subgraphs to the supergraph and defined our entities. Let’s test out @defer
with Explorer, our GraphQL IDE. You can test out ours here.
- Write a query that includes an entity (like products or reviews).
- Select the part you want to defer. Right-click to extract a fragment and add
@defer
. - Execute the query and you can see the data load dynamically
@defer
in a React app
Use Since @defer
returns multiple responses, the client must support a multipart format. Apollo Client and Apollo Kotlin both support @defer
today. Apollo iOS support is coming soon.
Here’s how to use @defer
in your React application:
- Install the latest version of Apollo Client (v3.7.0 or later):
npm install @apollo/client@latest
- Add
@defer
to your query with a fragment. - Ensure your React component expects the deferred data to be undefined since it might not be available right away.
Configure your router to secure your subgraph and set up CORS rules for your website. Below is an example of a configuration we used:
cors:
origins:
- https://studio.apollographql.com
- https://hack-the-supergraph.netlify.app
headers:
all:
request:
- insert:
name: "subgraph-token"
value: "${env.SUBGRAPH_SECRET}"
- propagate:
named: "authorization"
You can see @defer
in action in our e-commerce site example. It’s a product details page where we’re deferring the product’s reviews. To increase/decrease the latency for the deferred views, adjust the slider in “Demo Settings.”
@defer + GraphOS = 😍
Let’s recap what we learned! By implementing @defer
with Apollo GraphOS, we can improve our app’s TTI and reduce latency in 3 steps:
- Connect our GraphQL API to the supergraph.
- Define entities in our supergraph using
@key
. - Mark slow fields in our query with
@defer
.
To check out the code powering our example, here’s the frontend, the subgraphs, and Explorer. We’d love to hear your feedback in our community forums.
Happy querying!