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
1. Airlock, the Monolith
5m

Overview

Welcome to the second course of our Voyage series!

In the first course, we learned about Apollo Federation, how it works and how it helps us modularize our graphs and scale faster. We built an app called FlyBy using federation from day one!

In this course, we'll explore how federation can help solve problems in an existing, non-federated graph. We'll learn how to transform this existing monolithic graph into a federated graph (otherwise known as a supergraph).

To give us the observability and governance that we need to manage and build a federated graph, we'll power up our API with Apollo GraphOS. Apollo GraphOS is a complete cloud platform for building, managing, and scaling your graph: it provides a set of tools and services so that product developers can focus on building better apps, faster. We'll be using GraphOS to manage our graph, work with it locally, and migrate types and fields from our schema safely using the @override directive.

Before we get started, you should already be familiar with the following concepts that were covered in the first course of this series:

  • What Apollo Federation is
  • The components of a supergraph: subgraphs and the router
  • Using the Rover CLI

Note: This series is intended for backend developers who are comfortable working with an existing GraphQL server.


If you're a frontend developer who doesn't work on the backend, the good news is that your workflow stays the same, whether you're dealing with a federated or a non-federated graph. You'll still send all your GraphQL operations to a single endpoint, and the backend team will handle the rest!

All right, let's dive into what we're working with!

🪐 Introducing Airlock, our space travel app

Want to book a trip to new, exciting, sometimes-fictional places in the vast universe? Enter Airlock!

The Airlock app homepage with a list of places to book.

Using Airlock, you can find listings that meet your dates of choice and the number of beds you'll need. Learn what each place is all about and what amenities it offers, and if you're interested, you can book your stay in one click (provided you have enough space credits in your wallet of course)!

If you're looking to rent out your own space suite, you can do that with Airlock too! Add your listing to the platform with all the necessary details and start managing your bookings. After each stay, guests and hosts will leave honest ratings and reviews about each other.

Airlock's evolution story

Behind the scenes, Airlock's architecture looks something like this:

Diagram of Airlock's architecture showing one web client connected to the GraphQL server which in turn connects to multiple services

Airlock started out as a basic app with a small graph that defined very few types and fields. As its popularity and usage grew, new features were introduced, along with schema changes and additions.

Soon enough, the small unassuming app transformed into an unwieldy monolith. The developer experience is degrading as friction starts to creep in: schema changes and improvements are met with merge conflicts, inconsistencies and duplicated information. It's becoming difficult to navigate the large schema file! New features and bug fixes are taking longer to deploy.

Illustration of a small application that has transformed into an intimidatingly huge monster representing the monolith graph

The GraphQL server may look small in the diagram, but in reality, it more closely resembles a big monolith monster with many different business domains represented as types, queries, and mutations all contained in a single humongous .graphql file!

Additionally, we have multiple teams and developers responsible for these business domains. Let's meet a couple of them and what they're struggling with.

  • 👩🏽‍🚀 The Accounts Team says:

    "We're in charge of all things related to users, accounts, and user profiles! We think it's a fairly small scope to work within, so it's been a pain having to sift through all the other business domains in the schema that don't involve our intended changes."

  • 👩🏽‍🏫 The Listings Team says:

    "We deal with all the cool space rentals in Airlock: their information, amenities, and linking them back to a profile (which the Accounts team is responsible for). We definitely own a big chunk of what's in the schema right now and we make a lot of changes with new features and improvements! Oftentimes, we have merge conflicts with other teams."

There are a few more teams involved with Airlock development: the Bookings team, the Reviews team, and the Payments team. It's clear that all of them struggle with developing, growing, and scaling the graph as it stands.

To help our Airlock developers have a smoother experience, we're going to transform this monolith graph into a supergraph! We should already be familiar with the benefits of a federated architecture outlined in the first course, and those same benefits apply here!

An alternate journey of the supergraph

If you're not familiar with the journey of an operation through the supergraph, you can review it in Voyage I.

Our supergraph journey for this course will be similar to the one in the previous course, with one big exception: we're going to be starting from a monolith graph that we'll split incrementally into multiple subgraphs.

Let's revisit the journey!

A doodle demonstrating the journey of converting the monolith into a subgraph and publishing it to the registry to generate a supergraph schema

First, the monolith graph will be converted into a subgraph. This means all of the schema's types, fields, and behavior will still be preserved and working as usual.

Next, we're going to publish the subgraph to the GraphOS registry. This triggers composition.

If composition fails, we get error messages we'll need to fix! If composition succeeds, Uplink will be updated with our new supergraph schema.

Then, the router will fetch this schema and be ready to handle incoming queries using this new schema!

This is only the start of our supergraph journey! After this process, we'll go back to the start and split off another subgraph from the monolith subgraph. After we make changes to a subgraph, we'll need to publish our subgraph schemas again and follow the flow.

📋 The migration plan

Let's go over the implementation specifics for how to transform our large monolith into a supergraph!

First and foremost, we want to make sure that throughout this process, the web app client doesn't experience any issues and that queries continue to work as normal!

Here are the high-level steps for our migration plan:

  1. We'll convert the monolith GraphQL server into a subgraph server, which we'll run on a different port. (Yes, it's valid for a supergraph to have just one subgraph!) This subgraph will be published to the schema registry.

  2. We'll create a GraphOS Router running on the monolith's original port. The router will be connected to the schema registry and will handle all of the same queries that were previously being sent to the monolith server.

  3. We'll start to split off small chunks of our single monolith subgraph into new domain-specific subgraphs. This will take several steps, which we'll explain in more detail later on.

Does this process sound familiar to you? These steps apply the Strangler Fig approach: a migration technique that involves incrementally replacing an old system with new components until the old system is "strangled" and can be completely removed.

Diagram illustrating the steps outlined above

Practice

Which of these are common problems that developers experience with a monolithic GraphQL schema?

Key takeaways

  • A simple schema can potentially evolve into a big, intimidating schema that is difficult to navigate and work with for different teams. Federation solves these problems, but the process will be different when starting with an existing application compared to a greenfield app.

  • We want to avoid any issues with the client by following a migration plan that swaps the original monolith server with the router.

  • At the beginning, our supergraph schema will be composed of only one subgraph: the initial monolith schema.

Up next

Before we can get the migration plan into action, let's get Airlock up and running!

Next

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.

              Apollo Federation

              Apollo’s implementation of GraphQL Federation—an architecture for orchestrating multiple APIs into a single GraphQL API.

              graphs

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

              graph

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

              monolithic graph

              A graph that operates on a standalone GraphQL server which receives queries directly from client applications, without a router.

              graph

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

              graph

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

              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.

              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
              }
              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
              }
              Apollo Federation

              Apollo’s implementation of GraphQL Federation—an architecture for orchestrating multiple APIs into a single GraphQL API.

              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.

              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.

              Rover CLI

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

              GraphQL server

              A server that contains a GraphQL schema and can resolve client-requested operations that are executed against that schema.

              graph

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

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              operations

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

              graph

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

              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
              }
              GraphQL server

              A server that contains a GraphQL schema and can resolve client-requested operations that are executed against that schema.

              mutations

              A GraphQL operation that modifies data on the server. It allows clients to perform create, update, or delete operations, altering the underlying data.

              graph

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

              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.

              operation

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

              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.

              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.

              graph

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

              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.

              graph

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

              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.

              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.

              composition

              The process of combining subgraph schemas into a supergraph schema. A supergraph schema includes all definitions from subgraph schemas and additional metadata.

              composition

              The process of combining subgraph schemas into a supergraph schema. A supergraph schema includes all definitions from subgraph schemas and additional metadata.

              Uplink

              An Apollo-hosted endpoint for serving supergraph configurations to GraphOS Router and @apollo/gateway. Also serves the Enterprise license to GraphOS Router.

              supergraph schema

              A special type of GraphQL schema that is created by declaratively combining one or more subgraph schemas using the Apollo Federation specification.

              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 schemas

              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.

              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.

              GraphQL server

              A server that contains a GraphQL schema and can resolve client-requested operations that are executed against that schema.

              subgraph server

              A GraphQL server which acts as a module of a supergraph. Subgraph servers can be written in any federation-compatible language or library.

              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 Router

              A scalable runtime for supergraphs that's fully integrated with GraphOS and based on the Apollo Router Core. Can be cloud- or self-hosted.

              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.

              field

              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
              }
              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 schema

              A special type of GraphQL schema that is created by declaratively combining one or more subgraph schemas using the Apollo Federation specification.

              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.

              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