|
| 1 | +--- |
| 2 | +title: Scaling your GraphQL API |
| 3 | +--- |
| 4 | + |
| 5 | +As your application grows, so does your GraphQL schema. What starts as a small, |
| 6 | +self-contained monolith may eventually need to support multiple teams, services, and |
| 7 | +domains. |
| 8 | + |
| 9 | +This guide introduces three common patterns for structuring GraphQL APIs at different |
| 10 | +stages of scale: monolithic schemas, schema stitching, and federation. It also explains |
| 11 | +how these patterns relate to GraphQL.js and what tradeoffs to consider as your |
| 12 | +architecture evolves. |
| 13 | + |
| 14 | +## Monolithic schemas |
| 15 | + |
| 16 | +A monolithic schema is a single GraphQL schema served from a single service. All types, |
| 17 | +resolvers, and business logic are located and deployed together. |
| 18 | + |
| 19 | +This is the default approach when using GraphQL.js. You define the entire schema in one |
| 20 | +place using the `GraphQLSchema` constructor and expose it through a single HTTP endpoint. |
| 21 | + |
| 22 | +The following example defines a minimal schema that serves a single `hello` field: |
| 23 | + |
| 24 | +```js |
| 25 | +import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql'; |
| 26 | + |
| 27 | +const QueryType = new GraphQLObjectType({ |
| 28 | + name: 'Query', |
| 29 | + fields: { |
| 30 | + hello: { |
| 31 | + type: GraphQLString, |
| 32 | + resolve: () => 'Hello from a monolithic schema!', |
| 33 | + }, |
| 34 | + }, |
| 35 | +}); |
| 36 | + |
| 37 | +export const schema = new GraphQLSchema({ query: QueryType }); |
| 38 | +``` |
| 39 | + |
| 40 | +This structure works well for small to medium projects, especially when a single team owns the entire |
| 41 | +graph. It's simple to test, deploy, and reason about. As long as the schema remains manageable |
| 42 | +in size and scope, there's often no need to introduce additional architectural complexity. |
| 43 | + |
| 44 | +## Schema stitching |
| 45 | + |
| 46 | +As your application evolves, you may want to split your schema across modules or services while |
| 47 | +still presenting a unified graph to clients. Schema stitching allows you to do this by merging |
| 48 | +multiple schemas into one executable schema at runtime. |
| 49 | + |
| 50 | +GraphQL.js does not include stitching capabilities directly, but the |
| 51 | +[`@graphql-tools/stitch`](https://the-guild.dev/graphql/stitching/docs/approaches) package |
| 52 | +implements stitching features on top of GraphQL.js primitives. |
| 53 | + |
| 54 | +The following example stitches two subschemas into a single stitched schema: |
| 55 | + |
| 56 | +```js |
| 57 | +import { stitchSchemas } from '@graphql-tools/stitch'; |
| 58 | + |
| 59 | +export const schema = stitchSchemas({ |
| 60 | + subschemas: [ |
| 61 | + { schema: userSchema }, |
| 62 | + { schema: productSchema }, |
| 63 | + ], |
| 64 | +}); |
| 65 | +``` |
| 66 | + |
| 67 | +Each subschema can be developed and deployed independently. The stitched schema handles query delegation, |
| 68 | +merging, and resolution across them. |
| 69 | + |
| 70 | +Stitching is useful when: |
| 71 | + |
| 72 | +- Integrating existing GraphQL services behind a single endpoint |
| 73 | +- Incrementally breaking up a monolithic schema |
| 74 | +- Creating internal-only aggregators |
| 75 | + |
| 76 | +However, stitching can add runtime complexity and often requires manual conflict resolution for |
| 77 | +overlapping types or fields. |
| 78 | + |
| 79 | +## Federation |
| 80 | + |
| 81 | +Federation is a distributed architecture that composes a single GraphQL schema from multiple independently |
| 82 | +developed services, known as subgraphs. Each subgraph owns a portion of the schema and is responsible |
| 83 | +for defining and resolving its fields. |
| 84 | + |
| 85 | +Unlike schema stitching, federation is designed for large organizations where teams need autonomy over |
| 86 | +their part of the schema and services must be deployed independently. |
| 87 | + |
| 88 | +Federation introduces a set of conventions to coordinate between services. For example: |
| 89 | + |
| 90 | +- `@key` declares how an entity is identified across subgraphs |
| 91 | +- `@external`, `@requires`, and `@provides` describe field-level dependencies across service boundaries |
| 92 | + |
| 93 | +Rather than merging schemas at runtime, federation uses a composition step to build the final schema. |
| 94 | +A dedicated gateway routes queries to subgraphs and resolves shared entities. |
| 95 | + |
| 96 | +GraphQL.js does not provide built-in support for federation. To implement a federated subgraph using |
| 97 | +GraphQL.js, you'll need to: |
| 98 | + |
| 99 | +- Add custom directives to the schema |
| 100 | +- Implement resolvers for reference types |
| 101 | +- Output a schema that conforms to a federation-compliant format |
| 102 | + |
| 103 | +Most federation tooling today is based on |
| 104 | +[Apollo Federation](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/federation). |
| 105 | +However, other approaches exist: |
| 106 | + |
| 107 | +- [GraphQL Mesh](https://the-guild.dev/graphql/mesh) allows federation-like composition across |
| 108 | +services using plugins. |
| 109 | +- Custom gateways and tooling can be implemented using GraphQL.js or other frameworks. |
| 110 | +- The [GraphQL Composite Schemas WG](https://github.com/graphql/composite-schemas-wg/) (formed of Apollo, ChilliCream, The Guild, Netflix, Graphile and many more) are working on an open specification for the next generation of GraphQL Federation |
| 111 | + |
| 112 | +Federation is most useful when schema ownership is distributed and teams need to evolve their subgraphs |
| 113 | +independently under a shared contract. |
| 114 | + |
| 115 | +## Choosing the right architecture |
| 116 | + |
| 117 | +The best structure for your GraphQL API depends on your team size, deployment model, and how your |
| 118 | +schema is expected to grow. |
| 119 | + |
| 120 | +| Pattern | Best for | GraphQL.js support | Tooling required | |
| 121 | +|---|---|---|---| |
| 122 | +| Monolith | Default choice for most projects; simpler, faster, easier to reason about | Built-in | None | |
| 123 | +| Schema stitching | Aggregating services you control | External tooling required | `@graphql-tools/stitch` |
| 124 | +| Federation | Large enterprises; many teams contributing to a distributed graph independently | Manual implementation | Significant tooling and infrastructure | |
| 125 | + |
| 126 | +## Migration paths |
| 127 | + |
| 128 | +Architectural patterns aren't mutually exclusive. In many cases, teams evolve from one approach to another |
| 129 | +over time. |
| 130 | + |
| 131 | +### Monolith to schema stitching |
| 132 | + |
| 133 | +Schema stitching can act as a bridge when breaking apart a monolithic schema. Teams can extract parts |
| 134 | +of the schema into standalone services while maintaining a unified entry point. This allows for gradual |
| 135 | +refactoring without requiring a full rewrite. |
| 136 | + |
| 137 | +### Stitching to federation |
| 138 | + |
| 139 | +Federation formalizes ownership boundaries and removes the need to manually coordinate overlapping types. |
| 140 | +If schema stitching becomes difficult to maintain, federation can offer better scalability and governance. |
| 141 | + |
| 142 | +### Starting with federation |
| 143 | + |
| 144 | +Some teams choose to adopt federation early, particularly in large organizations with multiple backend |
| 145 | +domains and team boundaries already in place. This can work well if you have the infrastructure and |
| 146 | +experience to support it. |
| 147 | + |
| 148 | +## Guidelines |
| 149 | + |
| 150 | +The following guidelines can help you choose and evolve your architecture over time: |
| 151 | + |
| 152 | +- Start simple. If you're building a new API, a monolithic schema is usually the right place |
| 153 | +to begin. It's easier to reason about, test, and iterate on. |
| 154 | +- Split only when needed. Don't reach for composition tools prematurely. Schema stitching or federation |
| 155 | +should be introduced in response to real organizational or scalability needs. |
| 156 | +- Favor clarity over flexibility. Stitching and federation add power, but they also increase complexity. |
| 157 | +Make sure your team has the operational maturity to support the tooling and patterns involved. |
| 158 | +- Define ownership boundaries. Federation is most useful when teams need clear control over parts of |
| 159 | +the schema. Without strong ownership models, a federated graph can become harder to manage. |
| 160 | +- Consider alternatives. Not all use cases need stitching or federation. Sometimes, versioning, modular |
| 161 | +schema design, or schema delegation patterns within a monolith are sufficient. |
0 commit comments