5. Adding a subgraph


Let's give our something to sing about—literally! We're going to pair our soundtracks data with meals that need some music! With , it's straightforward: we're only a couple clicks away!

In this lesson, we will:

  • Add a new to our using Studio
  • Inspect an 's

Introducing recipes

Everyone needs a good soundtrack to go with the special dish they're whipping up! To that end, we're about to get to know the recipes API; it's another full-fledged with a schema, , and .

The coolest part? It's not a Java server. Instead, it's written in JavaScript and uses ! Remember, this isn't actually a problem for our : each we bring on board can be written using a different language or framework as necessary. We'll use our files, and datafetcher methods, to define how we'll pull data from both subgraphs—and match our meals to some music!

Right now, the recipes API is simply a small collection of recipes. We can ask for things like:

  • a random recipe
  • the full list of recipes in its database
  • the most recently added recipes
  • a particular recipe's ingredients, cooking time, instructions, and more

Let's welcome this and brand new functionality into our API—we can do this without cloning the repository or making any adjustments at all.

Adding a subgraph

  1. Head over to your 's page in Studio and navigate to the Subgraphs page. We can see that our soundtracks is already here, pointing to where we hosted it.

  2. Click Add a subgraph.

    Note: You can also add a using the . Click the arrow next to Add subgraph and select Add subgraph using the Rover CLI to find the instructions.


    The subgraphs page in Studio, outlining the Add a subgraph button

  3. We'll need to provide two things about the : its URL and its name.

    Routing URL
    Subgraph name

    A modal on the Subgraphs page, showing inputs for Routing URL and Subgraph Name

  4. Then, click Add Subgraph. It takes a few moments for to check that the successfully composes with all other existing subgraphs and produces a . And that's it!


    The Subgraphs page in Studio, showing details for two subgraphs: recipes and soundtracks

Our new supergraph schema

Let's check out the Changelog through the navigation menu to see what new features and capabilities the recipes has added to the API.


The Changelog page in Studio, showing additions to the schema from the recipes subgraph

We can see our has grown—with types and all about recipes! We've got Ingredient, Recipe, and several new added to our Query type like allRecipes and recentlyAddedRecipes.

All of these new types and are presumably all coming from the recipes . We can confirm which are coming from which subgraph by heading over to the Schema page.

Under the Reference tab, with Query selected, we can see the entry points to our . The Subgraph column indicates the each is coming from!


The Schema page in Studio, showing fields on the Query type and which subgraph provides them

We've got four new available from our Query entry point: allRecipes, randomRecipe, recentlyAddedRecipes, and a specific recipe.

Let's dig deeper into the Objects available in the schema.


The Schema page in Studio, showing the object types and which subgraph provides them

See that green "E" label on the Recipe type? It stands for ""! You can hover over it for more information, but we'll get to it in a later lesson, so stay tuned.

Our has officially grown!

Sending a query

With both soundtrack and recipe data at our fingertips, are you itching to put the power of our to the test? Let's try sending a that involves both .

Let's jump back to the Query tab in the Schema page, where we could see all our available entry points to the . Under the Actions column of the Schema page, click the Play icon right next to the recipe .


The play button beside the recipe field outlined

This will open up Explorer with the Documentation tab showing the and what we can use to build our .


The Explorer with the Documentation tab opened to the recipe field

Note: If you have an currently in the Operation panel, clear it or open up a new Explorer tab. We want to start fresh here!

Under recipe we can see its description—Returns a specific recipe based on its ID—along with the for a Recipe type. Let's add the name, cookingTime, description, and instructions.

query Recipe($recipeId: ID!) {
recipe(id: $recipeId) {

Because this returns data for a specific recipe, we need to give it an ID. Here's what we can paste into the Variables panel.

"recipeId": "recgUKbxnQssl9fYc"

That's data from the recipes ! Let's bring data from the soundtracks into the mix! Why don't we pull in data for featured playlists?

There's a handy shortcut in Explorer to search our schema for that . Hit Command + K or Ctrl + K to access the spotlight search. Start typing featuredPlaylists and the Query.featuredPlaylists should pop up.


The Explorer with the search modal pulled up, and Query.featuredPlaylists selected from the dropdown

Let's add the featuredPlaylists and ask for the name of each playlist as the sub.

Lastly, we'll rename the to be more explicit. Give it the name GetRecipeAndPlaylists.

Your should now look like this:

query GetRecipeAndPlaylists($recipeId: ID!) {
recipe(id: $recipeId) {
featuredPlaylists {

And under the Variables section:

"recipeId": "recgUKbxnQssl9fYc"

Before running the , let's click the dropdown in the Response panel and first inspect the Query Plan Preview.

This diagram shows how the plans to execute the that we've written in the Operation panel. We can see the word "Parallel", indicating that the can make two separate requests simultaneously: one to recipes and one to soundtracks. These requests can run in parallel because neither soundtracks nor recipes depend upon the other's response to resolve their own data.


The Response panel opened to the Query Plan Preview, which shows how the router will execute the query to the subgraphs

Cool—now let's actually run it!

Woohoo, and we get data back! One query, but with data coming from two separate subgraphs 🤯🎉

The query plan

We can validate where exactly the data for each is coming from by inspecting the query plan. The is like a blueprint for an : the set of instructions that the uses to send smaller operations to the responsible for those particular .

Click on the arrow beside Response and select "Query plan". We can view this as a chart, or as text if we select the icon to "Show plan as text". We won't worry too much about the syntax—the knows what's going on! But this is useful when we start to involve more and more complex queries that need optimization.

Query plan preview in text format, showing which subgraph each field is fetched from

For this particular , we can see that the recipe and its subfields are coming from the recipes , and the featuredPlaylists and its subfields are coming from the soundtracks . Both of those smaller are run in parallel and resolved by its own subgraph, and the takes care of bundling them up to return in one single response back to the client.

Adding a was pretty straightforward! But you might be feeling that the data in both subgraphs is still separate and siloed. There's nothing directly connecting soundtracks to recipes or vice versa. We haven't yet achieved the experience that we want: with playlists being recommended to us based on the particular recipe we've selected.

The new feature: a recipe's recommended playlists

We want to ask for details about a specific recipe: its description, instructions, and ingredients, plus recommended playlists to cook with! For each playlist, we want to see the list of tracks as well.

A preview of what our recommended playlists feature looks like in action, providing a recipe with matching music

Here's what the dream looks like:

query GetRecipeAndRecommendedSoundtracks {
recipe(id: "rec3j49yFpY2uRNM1") {
ingredients {
recommendedPlaylists {
tracks {

Note: We're including the recipe's id inline with the here for ease of reference as we go through the course. In reality, this id would be extracted out into a .

We can correlate soundtracks data with a specific recipe by using at least one keyword—in our case, we'll use the recipe's name , and kick off a search with our soundtracks to find recommendations that might match the vibe of what we're cooking!

There's only one problem: the soundtracks doesn't have any idea what a recipe is, much less how to use its name to even start a search. Even though it's part of the same , it lives in its own world! And right now, the Recipe type and all of its live exclusively in the recipes .

So we'll need a way to connect the data between both to make our dream work (hint: it's called entities!).

This will involve some changes to our soundtracks service, so we'll first set up the right development environment. This will ensure that the changes we make to the soundtracks not only work as we expect, but that they also play nicely with the recipes !


To add a new subgraph, which of these values does GraphOS need to know?

Key takeaways

  • To add a new , we can use the Studio UI or .
  • We can view the 's using Explorer.

Up next

Let's set ourselves up for local development in the next lesson.


Share your questions and comments about this lesson

This course is currently in

. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.