3. Monolith as a subgraph
7m

Overview

In this lesson, we're going to tackle the first step for migrating our monolith app into a . We'll start by converting the monolith server into a single , which will run on a different port. Along the way, we'll also:

  • Review how to create a using
  • Publish our first to
Diagram of the migration plan step 1. Step 1 was to create a single large subgraph with the exact same schema as the monolith, and run it on a different port. This single subgraph will be published to the registry.

Service check

Let's make sure all of our processes are still running from the previous lesson.

  • One terminal should be running npm start, to start the monolith server on port 4000.
  • Another terminal should be running npm run launch, to start our services in the monolith directory on ports 4010 and 4011.

✏️ Importing packages

  1. Let's stop the main monolith server process with CTRL+C.

  2. Then, install the @apollo/subgraph package.

    monolith
    npm install @apollo/subgraph

    This directory contains an index.js file, which is running our monolith server. Let's adjust it slightly to turn it into a monolith subgraph server instead.

  3. To make this server a , we'll need to import the buildSubgraphSchema method from the @apollo/subgraph package. Add the following line to the imports in your index.js file:

    monolith/index.js
    const { buildSubgraphSchema } = require("@apollo/subgraph");

✏️ Updating the monolith server

Next, let's modify our ApolloServer instance. Right now, we pass our typeDefs and resolvers directly to the ApolloServer constructor.

monolith/index.js
const server = new ApolloServer({
typeDefs,
resolvers,
});

To convert this server into a , let's define a schema property in the constructor instead. We'll use the buildSubgraphSchema method, as we did in the first course, passing it an object that contains the typeDefs and resolvers.

monolith/index.js
const server = new ApolloServer({
schema: buildSubgraphSchema({
typeDefs,
resolvers,
}),
});

While we're here, let's also set our server to listen on port 4001 (a different port from where it was originally running!). We want the monolith to use a different port because, as we outlined in our migration plan, we'll set up the to take over port 4000. This way, the client doesn't need to make any changes to communicate with the .

Set up the server's listen function to run on port 4001.

monolith/index.js
- const port = 4000;
+ const port = 4001;

✏️ Federation 2 subgraph schema definition

We'll want to make sure to opt in to the latest Federation 2 features for this . Open up the schema.graphql file in the same monolith directory and add the following snippet at the top:

monolith/schema.graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.7",
import: ["@key"])

With this line, we can specify the various we'd like to use within our schema file (such as @key, as shown in the import).

With that, we're ready to restart our monolith server process!

monolith
npm start

We'll see some output in our console and then the message "🚀 Server ready at http://localhost:4001/".

Testing the monolith subgraph

Let's visit that URL http://localhost:4001 in the browser to open up again. Let's try out the same from the previous lesson to make sure everything is still working as before!

query GetAllAmenities {
listingAmenities {
category
name
}
}

After running the , we can see data showing up in the Response panel on the right. Great, we know it's working! By transforming the monolith schema into a , we know that all of our schema's types, , and features are still preserved and intact.

We've got our first ready, so the next step is to publish it to the registry!

Publishing our subgraph

Recall that the rover subgraph publish command looks like this:

rover subgraph publish <APOLLO_GRAPH_REF> \
--schema <SCHEMA_FILE_PATH> \
--name <SUBGRAPH_NAME> \
--routing-url <SERVER_URL>

Let's publish this !

Tip: We're going to be using a few different commands as we go through the course. You can create a new file to store these commands and copy-paste them to the terminal when you need them, or you can incorporate them into scripts to run in the package.json file.

Open up a new terminal window in the root directory and run the command below, substituting the values of the APOLLO_GRAPH_REF flag to match your own. We're going to name this monolith.

rover subgraph publish <APOLLO_GRAPH_REF> \
--schema ./monolith/schema.graphql \
--name monolith \
--routing-url http://localhost:4001

We'll get a message asking if we want to publish with a localhost URL.

The host `localhost` is not routable via the public internet.
Continuing the publish will make this subgraph reachable in local environments only.
Would you still like to publish? [y/N]

We're in tutorial land, so we're working with local endpoints for now. Type y and hit enter.

Uh-oh... when we run the command, we'll see that we get an error back in the terminal! (You'll see the value of your own APOLLO_GRAPH_REF in place of the flag below.)

error[E007]: The graph `[APOLLO_GRAPH_REF]` is a non-federated graph.
This operation is only possible for federated graphs.
If you are sure you want to convert a non-federated graph to a subgraph, you can re-run the same command with a `--convert` flag.

But what went wrong?

Well, when we set up our , we chose a monolith architecture, which created a non-federated . This was suitable for our purposes at the time, but now that we're breaking down the monolith into , we need to make sure our graph is federated.

Let's try that command again, this time including the --convert flag, as the error message suggests.

rover subgraph publish <APOLLO_GRAPH_REF> \
--schema ./monolith/schema.graphql \
--name monolith \
--routing-url http://localhost:4001 \
--convert

The addition of the --convert flag at the end will tell Studio to convert the existing into a .

And now we should see that the command ran successfully, and our was published!

Task!
Illustration of the monolith being turned into a subgraph as the first step of our migration plan.

A subgraph is born!

In the browser, let's get back to the in Studio. We'll see a new label at the top indicating that it's federated, along with the specific federation version.

studio.apollographql.com

Studio with federated graph

Let's navigate to the Subgraphs page. We can see we have one , monolith and all its details. (If you don't see the Subgraphs menu option, try refreshing the page!)

studio.apollographql.com

Subgraphs page showing monolith

That's step 1 done!

Practice

Which of these does the migration plan enable us to do when converting the monolith into a supergraph?

Key takeaways

  • We set up the monolith to use port 4001 because, as we outlined in our migration plan, we want the to take over port 4000. (Don't worry - we haven't gotten there yet!) This way, the client doesn't need to make any changes to communicate with the .
  • To convert an existing in Studio into a , we use the same rover subgraph publish command to publish a schema, and add a --convert flag.

Up next

Let's review our migration plan. We can successfully check off the first step, so let's see what's up next:

  1. Convert the monolith GraphQL server into a subgraph server, which we'll run on a different port. This subgraph will be published to the schema registry.
Diagram of the migration plan step 1. Step 1 was to create a single large subgraph with the exact same schema as the monolith, and run it on a different port. This single subgraph will be published to the registry.
  1. ➡️ Create a 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.

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

The next step is to configure the . This router needs to handle authentication and authorization in Airlock, so let's learn about how that works in the next lesson.

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.