Odyssey

Voyage II: Federating the Monolith

Airlock, the MonolithMonolith graph setupMonolith as a subgraphAuth in a supergraphConfiguring the routerSubgraph planningDefine entitiesA stub subgraphUsing @override to migrate fieldsImplementing resolversFinishing up the subgraph
11. Finishing up the subgraph
5m

Overview

We're nearing the end! In this lesson, we will:

  • Run a few queries to test our changes
  • Publish the new accounts schema to GraphOS

Testing our changes

We've got a few queries to test. We'll run each query in our locally-running Explorer at http://localhost:4000 and make sure we get data back. We'll also take a peek at the query plan to verify the correct fields are coming from the accounts subgraph.

Testing a root field

Testing a root field
query GetMyProfile {
me {
id
name
profilePicture
... on Host {
profileDescription
}
}
}

Make sure your Headers are set to:

Authorization: Bearer user-1

You should get back:

Data response
{
"data": {
"me": {
"id": "user-1",
"name": "Eves",
"profilePicture": "https://res.cloudinary.com/apollographql/image/upload/odyssey/airlock/user-1.png",
"profileDescription": "I've been to 15 different planets and decided to make a home for myself and others in my favourites. Each planet and location has its own distinct environment, so read the description carefully. I have equipped them all with the necessary amenities."
}
}
}

And the query plan should show these types and fields coming from the accounts subgraph!

studio.apollographql.com

Query plan for me field host

Testing a listing's host

Testing the entity representations
query GetListingHost {
listing(id: "listing-1") {
host {
name
profilePicture
profileDescription
}
}
}

You should get back:

Data response
{
"data": {
"listing": {
"host": {
"name": "Eves",
"profilePicture": "https://res.cloudinary.com/apollographql/image/upload/odyssey/airlock/user-1.png",
"profileDescription": "I've been to 15 different planets and decided to make a home for myself and others in my favourites. Each planet and location has its own distinct environment, so read the description carefully. I have equipped them all with the necessary amenities."
}
}
}
}

Testing a review's author

query GetListingReviewsAuthor {
listing(id: "listing-1") {
reviews {
author {
id
name
}
}
}
}

The query plan should show the listing and reviews fields coming from the monolith subgraph, and the author fields coming from the accounts subgraph!

studio.apollographql.com

Query plan for review author

Feel free to play around with some other queries and examine the corresponding query plan!

Publishing our subgraph schemas

Ready to bring these changes to our supergraph? Let's go, you know the drill!

In a terminal window, from the root directory, run the following:

rover subgraph publish <APOLLO_GRAPH_REF> \
--schema ./subgraph-accounts/schema.graphql \
--name accounts

Remember to replace the <APOLLO_GRAPH_REF> value with your own!

If there's an error in the terminal, have no fear! These troubleshooting tips cover a few of the most common scenarios we might encounter when publishing our subgraph.

Failed authentication

Rover might indicate that publishing failed due to malformed or invalid credentials.

The error message: error[E014]: The API key you provided is malformed. An API key must have three parts separated by a colon.

How to fix it:

  • Double-check that the key used to configure Rover matches the APOLLO_KEY provided for your graph. If necessary, generate a new key for your graph by visiting the Settings tab in GraphOS Studio, then rerun rover config auth.
  • You can also check the identity of your configured API key by running the command rover config whoami. An invalid API key produces the error below: error[E013]: The registry did not recognize the provided API key. Check your API key to make sure it's valid (are you using the right profile?).

For more information about configuring Rover to work with graph keys, see the docs on configuring Rover.

Invalid path

Rover might indicate that it can't find a schema file at the specified location.

The error message: error: Invalid path. No file found at ./subgraph-accounts/schema.graphql

How to fix it: Make sure to run the rover subgraph publish command from the root directory of your project. The path to the subgraph schema file should be relative from that directory.

Syntax error

Rover might indicate an error parsing the schema if one of the subgraph files contains invalid syntax.

The error message: error: Could not parse partial schema as AST.

How to fix it: Check the schema and server files for errors, or revisit Lessons 2 and 3 to validate your code.

Seeing another error?

For any other scenarios not covered here, please see the official docs on Rover errors.

Still having trouble? Visit the Odyssey forums to get help.

Testing our changes

Feel free to run the same operations as in the earlier section (refer back to Lesson 5 where we ran the router locally) to make sure everything's working correctly!

Let's head over to the Schema page and scroll down the list to find the me and user fields. We can see that the accounts subgraph is now listed together with the monolith column.

studio.apollographql.com

Query plan for listing host

Returning to the client

We should still have our client application running on port 3000. If not, navigate to the client directory and run npm start.

Returning to the app, however, we see an error on the homepage!

http://localhost:3000
The homepage of Airlock's client app, displaying a failed to fetch error

When we check out the errors in the console, we'll find a message that might be familiar from the first course in this series.

Access to fetch at 'http://localhost:4000' from origin 'http://localhost:3000'
has been blocked by CORS policy

In Voyage I, we saw how to modify our router's config.yaml file to allow requests from a client to reach our supergraph. Let's add the CORS options to our config.yaml file now to permit our client app at http://localhost:3000 to talk to our router.

Note: You can read more about CORS (and why it's important) in the Apollo documentation.

CORS configuration

Open up router-config.yaml in the server's router directory. At the bottom of the file, we'll add the following configuration:

router/router-config.yaml
include_subgraph_errors:
all: true # Propagate errors from all subgraphs
headers:
all:
request:
- propagate:
named: "Authorization"
cors:
origins:
- http://localhost:3000 # Allows any locally-running client to run against your Router
- https://studio.apollographql.com # Allows Studio to still run queries against your Router

These rules will continue to allow requests from Studio to reach our supergraph, and will now also permit requests from our frontend app.

Navigate to the terminal where your router is currently running. Stop the server process, and then restart it. When we refresh http://localhost:3000, we'll see that we're getting data back!

http://localhost:3000
The homepage of Airlock's client app, now displaying data about listings

If an error occurs when loading the client application, we might have missed a step along the way. Here are some troubleshooting tips for getting things up and running:

  • CORS issue: Your browser console message is displaying a CORS message such as "Access to fetch at [URL] from origin http://localhost:3000 has been blocked by CORS policy". To fix this, go back to your router's config.yaml file where you set up the CORS configuration.

    Make sure your file's CORS configuration looks like the code below and that there is no slash (/) at the end of the URLs specified.

router/router-config.yaml
cors:
origins:
- http://localhost:3000 # Allows any locally-running client to run against your Router
- https://studio.apollographql.com # Allows Studio to still run queries against your Router

Still having trouble? Visit the Odyssey forums to get help.

Over time, as we monitor the performance of the accounts subgraph and deem it successful, we'll reach a point where we can safely remove the fields in the monolith subgraph. Then, we can remove the @override directive entirely!

Note: If you used progressive override, you would slowly increase the traffic going into the overriding subgraph until it reached 100%. At that point, you can safely remove the fields in the other subgraph.

Key takeaways

  • Splitting off subgraphs incrementally enables teams to reap the benefits of federation sooner.
  • Use the @override directive to migrate fields safely between subgraphs.
  • The router configuration file takes an option to define a CORS policy, which allows the origins you specify to communicate with your router.

Checking in with the Airlock team

Congratulations, we're on our way to a complete supergraph! Remember our monolithic monster at the beginning of the course that teams were intimidated by and struggling with? Let's see what they have to say about it now:

  • 👩🏽‍🚀 The Accounts Team says:

    "It's great being able to focus on our own subgraph responsibilities! We're much faster at making changes and pushing updates compared to before. Excited for the new features incoming!"

  • 👩🏽‍🏫 The Listings Team says:

    "With the accounts subgraph completed, the monolith schema is a little more manageable. We're excited to get our team's domain responsibilities on our own subgraph too! The heavy lifting was already done for us with the router setup and the first subgraph out of the way, so we can use that as a blueprint to get our own listings subgraph started."

An illustration of the monolith monster transforming into a supergraph.

Amazing, we've made big leaps and improvements to the developer experience that will set us up for great things to come in Airlock's future!

Conclusion

In this course, we learned the process of how to migrate from a monolith graph to a supergraph. We first converted the original graph into one large subgraph, which we published to GraphOS. Then, we installed and ran a router using the same URL as the original graph, so that the client wouldn't need any changes.

We learned how to prepare and plan for splitting subgraphs by identifying entities, grouping entities, and sorting out which types and fields belong where. We started with the accounts subgraph, learning how to use a stub subgraph to get started. Then we used the @override directive to safely migrate fields over from the monolith subgraph to the accounts subgraph.

We've still got four more subgraphs to go before our supergraph is complete, and you have all the tools you need to tackle those!

In the next course of the Voyage series, we'll take a look at how to bring Airlock to production and how to use GraphOS features like variants, schema checks, and observability. See you in Voyage III: Federation in Production!

Previous

Share your questions and comments about this lesson

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.

              GraphOS

              A platform for building and managing a supergraph. It provides a management plane to test and ship changes and runtime capabilities to secure and monitor the graph.

              query

              A request for specific data from a GraphQL server. Clients define the structure of the response, enabling precise and efficient data retrieval.

              query plan

              A strategy for executing an incoming operation efficiently. A query plan divides a single incoming operation into one or more operations that are each resolvable by a single subgraph.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              query plan

              A strategy for executing an incoming operation efficiently. A query plan divides a single incoming operation into one or more operations that are each resolvable by a single subgraph.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              query plan

              A strategy for executing an incoming operation efficiently. A query plan divides a single incoming operation into one or more operations that are each resolvable by a single subgraph.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              query plan

              A strategy for executing an incoming operation efficiently. A query plan divides a single incoming operation into one or more operations that are each resolvable by a single subgraph.

              supergraph

              A unified, federated graph composed of separate GraphQL APIs using Apollo Federation. Enables a microservices architecture that exposes a unified GraphQL API to clients.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              Rover

              Apollo's command-line interface for managing and maintaining graphs with GraphOS.

              Rover

              Apollo's command-line interface for managing and maintaining graphs with GraphOS.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              GraphOS Studio

              The web interface for GraphOS, which provides graph, variant, and organization management, metrics visualization, schema pipeline tools and more.

              Rover

              Apollo's command-line interface for managing and maintaining graphs with GraphOS.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              Rover

              Apollo's command-line interface for managing and maintaining graphs with GraphOS.

              subgraph schema

              A schema for a subgraph server. A subgraph schema must be compliant with the GraphQL and Apollo Federation specs to be composed into a supergraph.

              Rover

              Apollo's command-line interface for managing and maintaining graphs with GraphOS.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              operations

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              supergraph

              A unified, federated graph composed of separate GraphQL APIs using Apollo Federation. Enables a microservices architecture that exposes a unified GraphQL API to clients.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              supergraph

              A unified, federated graph composed of separate GraphQL APIs using Apollo Federation. Enables a microservices architecture that exposes a unified GraphQL API to clients.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              directive

              A GraphQL annotation for a schema or operation that customizes request execution. Prefixed with @ and may include arguments. For example, the @lowerCase directive below can define logic to return the username field in lowercase:

              type User {
              username: String! @lowerCase
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              directive

              A GraphQL annotation for a schema or operation that customizes request execution. Prefixed with @ and may include arguments. For example, the @lowerCase directive below can define logic to return the username field in lowercase:

              type User {
              username: String! @lowerCase
              }
              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              supergraph

              A unified, federated graph composed of separate GraphQL APIs using Apollo Federation. Enables a microservices architecture that exposes a unified GraphQL API to clients.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              supergraph

              A unified, federated graph composed of separate GraphQL APIs using Apollo Federation. Enables a microservices architecture that exposes a unified GraphQL API to clients.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              GraphOS

              A platform for building and managing a supergraph. It provides a management plane to test and ship changes and runtime capabilities to secure and monitor the graph.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              entities

              An object type of Apollo Federation that can be fetched with one or more unique keys. Can resolve its fields from multiple data sources in a federated graph.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              directive

              A GraphQL annotation for a schema or operation that customizes request execution. Prefixed with @ and may include arguments. For example, the @lowerCase directive below can define logic to return the username field in lowercase:

              type User {
              username: String! @lowerCase
              }
              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              supergraph

              A unified, federated graph composed of separate GraphQL APIs using Apollo Federation. Enables a microservices architecture that exposes a unified GraphQL API to clients.

              GraphOS

              A platform for building and managing a supergraph. It provides a management plane to test and ship changes and runtime capabilities to secure and monitor the graph.

              variants

              Independent instances of a graph often used to represent different environments. Each variant has its own schema and own router.

              schema checks

              A GraphOS feature that ensures proposed subgraph schema changes successfully compose into a supergraph schema, don't break active clients, and follow best practices.

              NEW COURSE ALERT

              Introducing Apollo Connectors

              Connectors are the new and easy way to get started with GraphQL, using existing REST APIs.

              Say goodbye to GraphQL servers and resolvers—now, everything happens in the schema!

              Take the course