Schema stitching is the process of creating a single GraphQL gateway schema from multiple underlying GraphQL APIs.
One of the main benefits of GraphQL is that we can query for all of our data in a single request from one schema. As that schema grows though, it may become cumbersome to manage it all in one codebase. It may become preferable to split the schema into seperate modules or microservices that can be developed and deployed independently. We may also want to integrate our own schema with third-party schemas.
In these cases,
stitchSchemas is used to combine multiple GraphQL schemas into one unified gateway schema that knows how to delegate parts of a query to the relevant underlying subschemas. These subschemas may be local GraphQL instances or APIs running on a remote server. They can even be third-party services, allowing us to create mashups with external data.
In this example we'll stitch together two very simple schemas. We'll be dealing with a system of users and "chirps"—or, small snippets of text that users can post.
This process builds two (mocked) GraphQL schemas, places them each into subschema configuration wrappers, and then passes the subschema configs to
stitchSchems to produce one combined schema with the following root fields:
We now have a single gateway schema that allows data from either subschema to be requested in the same query!
In the example above, the extra "subschema" wrapper objects may look verbose at first glance, but they are actually basic implementations of the
SubschemaConfig interface that accept several additional settings (discussed throughout this guide):
Subschema config should directly provide as many settings as possible to avoid unnecessary layers of delegation. For example, while
wrapSchema could be used to pre-wrap a schema with transforms and a remote executor, that would be far less efficient than providing the
executor options directly to subschema config.
Also note that the original subschema config objects will need to be referenced again in other stitching contexts. With that in mind, you'll probably want to export your subschema configs from their module(s) so they may be referenced throughout your app.
Stitching remote schemas
To include a remote schema in the combined gateway, we must provide subschema config for—at minimum—a schema and an executor that connects to the remote API:
The remote schema's type definitions string may be obtained via introspection (see
introspectSchema) or through your own internal protocol.
An executor is a generic method that performs requests to a remote schema. You may write your own, or use the
linkToExecutor helper to wrap a link package such as apollo-link-http. Subschema config accepts an
executor option for query and mutation operations, and a
subscriber function for subscription operations. See the remote schema docs for more information.
For pre-version 5: the old method of using makeRemoteExecutableSchema to create a local proxy of a remote schema still works. However, it adds an additional layer of delegation that can be avoided by sending settings directly to
stitchSchemas via SubschemaConfig.
Duplicate type definitions
By default, schema stitching will override type definitions that are duplicated across subschemas—always favoring the final definition of fields, arguments, and descriptions for a type found in the
subschemas array. This works fine when subschemas implement identical versions of an object type. For divergent type definitions, you may now enable type merging (as of GraphQL Tools 5) to smartly merge partial type definitions from across subschemas.
Another strategy to avoid conflicts while combining schemas is to modify one or more of the schemas using transforms. Transforming allows a schema to be groomed in such ways as adding namespaces, renaming types, or removing fields (to name a few) prior to stitching it into the combined gateway schema. As of GraphQL Tools version 5, these transforms should be added directly to subschema config:
In the example above, we transform the
chirpSchema by removing the
chirpsByAuthorId root field and adding a
Chirp_ prefix to all types. These modifications will only be present in the combined gateway schema.