From 0e985f3ffad0c0721bbf212b0c07d5500c7ae073 Mon Sep 17 00:00:00 2001 From: sarahxsanders Date: Tue, 27 May 2025 17:05:32 -0400 Subject: [PATCH 1/4] add guide on scaling your api --- website/pages/docs/_meta.ts | 1 + website/pages/docs/scaling-graphql.mdx | 160 +++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 website/pages/docs/scaling-graphql.mdx diff --git a/website/pages/docs/_meta.ts b/website/pages/docs/_meta.ts index 9b09249e88..48085fa03b 100644 --- a/website/pages/docs/_meta.ts +++ b/website/pages/docs/_meta.ts @@ -31,6 +31,7 @@ const meta = { title: 'FAQ', }, 'going-to-production': '', + 'scaling-graphql': '', }; export default meta; diff --git a/website/pages/docs/scaling-graphql.mdx b/website/pages/docs/scaling-graphql.mdx new file mode 100644 index 0000000000..df71ece8f1 --- /dev/null +++ b/website/pages/docs/scaling-graphql.mdx @@ -0,0 +1,160 @@ +--- +title: Scaling your GraphQL API +--- + +As your application grows, so does your GraphQL schema. What starts as a small, +self-contained monolith may eventually need to support multiple teams, services, and +domains. + +This guide introduces three common patterns for structuring GraphQL APIs at different +stages of scale: monolithic schemas, schema stitching, and federation. It also explains +how these patterns relate to GraphQL.js and what tradeoffs to consider as your +architecture evolves. + +## Monolithic schemas + +A monolithic schema is a single GraphQL schema served from a single service. All types, +resolvers, and business logic are located and deployed together. + +This is the default approach when using GraphQL.js. You define the entire schema in one +place using the `GraphQLSchema` constructor and expose it through a single HTTP endpoint. + +The following example defines a minimal schema that serves a single `hello` field: + +```js +import { GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql'; + +const QueryType = new GraphQLObjectType({ + name: 'Query', + fields: { + hello: { + type: GraphQLString, + resolve: () => 'Hello from a monolithic schema!', + }, + }, +}); + +export const schema = new GraphQLSchema({ query: QueryType }); +``` + +This structure works well for small to medium projects, especially when a single team owns the entire +graph. It's simple to test, deploy, and reason about. As long as the schema remains manageable +in size and scope, there's often no need to introduce additional architectural complexity. + +## Schema stitching + +As your application evolves, you may want to split your schema across modules or services while +still presenting a unified graph to clients. Schema stitching allows you to do this by merging +multiple schemas into one executable schema at runtime. + +GraphQL.js does not include stitching capabilities directly, but the +[`@graphql-tools/stitch`](https://the-guild.dev/graphql/stitching/docs/approaches) package +implements stitching features on top of GraphQL.js primitives. + +The following example stitches two subschemas into a single gateway schema: + +```js +import { stitchSchemas } from '@graphql-tools/stitch'; + +export const schema = stitchSchemas({ + subschemas: [ + { schema: userSchema }, + { schema: productSchema }, + ], +}); +``` + +Each subschema can be developed and deployed independently. The gateway handles query delegation, +merging, and resolution across them. + +Stitching is useful when: + +- Integrating existing GraphQL services behind a single endpoint +- Incrementally breaking up a monolithic schema +- Creating internal-only aggregators + +However, stitching can add runtime complexity and often requires manual conflict resolution for +overlapping types or fields. + +## Federation + +Federation is a distributed architecture that composes a single graph from multiple independently +developed services, known as subgraphs. Each subgraph owns a portion of the schema and is responsible +for defining and resolving its fields. + +Unlike schema stitching, federation is designed for large organizations where teams need autonomy over +their part of the schema and services must be deployed independently. + +Federation introduces a set of conventions to coordinate between services. For example: + +- `@key` declares how an entity is identified across subgraphs +- `@external`, `@requires`, and `@provides` describe field-level dependencies across service boundaries + +Rather than merging schemas at runtime, federation uses a composition step to build the final schema. +A dedicated gateway routes queries to subgraphs and resolves shared entities. + +GraphQL.js does not provide built-in support for federation. To implement a federated subgraph using +GraphQL.js, you'll need to: + +- Add custom directives to the schema +- Implement resolvers for reference types +- Output a schema that conforms to a federation-compliant format + +Most federation tooling today is based on +[Apollo Federation](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/federation). +However, other approaches exist: + +- [GraphQL Mesh](https://the-guild.dev/graphql/mesh) allows federation-like composition across +services using plugins. +- Custom gateways and tooling can be implemented using GraphQL.js or other frameworks. + +Federation is most useful when schema ownership is distributed and teams need to evolve their subgraphs +independently under a shared contract. + +## Choosing the right architecture + +The best structure for your GraphQL API depends on your team size, deployment model, and how your +schema is expected to grow. + +| Pattern | Best for | GraphQL.js support | Tooling required | +|---|---|---|---| +| Monolith | Simpler apps and single-team ownership | Built-in | None | +| Schema stitching | Aggregating services you control | External tooling required | `@graphql-tools/stitch` +| Federation | Distributed graphs across many teams | Manual implementation | Apollo Federation or custom | + +## Migration paths + +Architectural patterns aren't mutually exclusive. In many cases, teams evolve from one approach to another +over time. + +### Monolith to schema stitching + +Schema stitching can act as a bridge when breaking apart a monolithic schema. Teams can extract parts +of the schema into standalone services while maintaining a unified entry point. This allows for gradual +refactoring without requiring a full rewrite. + +### Stitching to federation + +Federation formalizes ownership boundaries and removes the need to manually coordinate overlapping types. +If schema stitching becomes difficult to maintain, federation can offer better scalability and governance. + +### Starting with federation + +Some teams choose to adopt federation early, particularly in large organizations with multiple backend +domains and team boundaries already in place. This can work well if you have the infrastructure and +experience to support it. + +## Guidelines + +The following guidelines can help you choose and evolve your architecture over time: + +- Start simple. If you're building a new API, a monolithic schema is usually the right place +to begin. It's easier to reason about, test, and iterate on. +- Split only when needed. Don't reach for composition tools prematurely. Schema stitching or federation +should be introduced in response to real organizational or scalability needs. +- Favor clarity over flexibility. Stitching and federation add power, but they also increase complexity. +Make sure your team has the operational maturity to support the tooling and patterns involved. +- Define ownership boundaries. Federation is most useful when teams need clear control over parts of +the schema. Without strong ownership models, a federated graph can become harder to manage. +- Consider alternatives. Not all use cases need stitching or federation. Sometimes, versioning, modular +schema design, or schema delegation patterns within a monolith are sufficient. \ No newline at end of file From 4c6796b8ab942d671911419a17c0d292ecf31549 Mon Sep 17 00:00:00 2001 From: sarahxsanders Date: Tue, 27 May 2025 17:10:17 -0400 Subject: [PATCH 2/4] fix cspell --- cspell.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cspell.yml b/cspell.yml index ab32211f7c..4f0e60b008 100644 --- a/cspell.yml +++ b/cspell.yml @@ -27,6 +27,8 @@ overrides: - xlink - composability - deduplication + - subschema + - subschemas ignoreRegExpList: - u\{[0-9a-f]{1,8}\} From 7f455b042f85e5a056f85c1176d63bb6b7e082fc Mon Sep 17 00:00:00 2001 From: Benjie Date: Thu, 29 May 2025 13:19:37 +0100 Subject: [PATCH 3/4] Apply suggestions from code review --- website/pages/docs/scaling-graphql.mdx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/website/pages/docs/scaling-graphql.mdx b/website/pages/docs/scaling-graphql.mdx index df71ece8f1..7a29b313f4 100644 --- a/website/pages/docs/scaling-graphql.mdx +++ b/website/pages/docs/scaling-graphql.mdx @@ -51,7 +51,7 @@ GraphQL.js does not include stitching capabilities directly, but the [`@graphql-tools/stitch`](https://the-guild.dev/graphql/stitching/docs/approaches) package implements stitching features on top of GraphQL.js primitives. -The following example stitches two subschemas into a single gateway schema: +The following example stitches two subschemas into a single stitched schema: ```js import { stitchSchemas } from '@graphql-tools/stitch'; @@ -64,7 +64,7 @@ export const schema = stitchSchemas({ }); ``` -Each subschema can be developed and deployed independently. The gateway handles query delegation, +Each subschema can be developed and deployed independently. The stitched schema handles query delegation, merging, and resolution across them. Stitching is useful when: @@ -78,7 +78,7 @@ overlapping types or fields. ## Federation -Federation is a distributed architecture that composes a single graph from multiple independently +Federation is a distributed architecture that composes a single GraphQL schema from multiple independently developed services, known as subgraphs. Each subgraph owns a portion of the schema and is responsible for defining and resolving its fields. @@ -107,6 +107,7 @@ However, other approaches exist: - [GraphQL Mesh](https://the-guild.dev/graphql/mesh) allows federation-like composition across services using plugins. - Custom gateways and tooling can be implemented using GraphQL.js or other frameworks. +- 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 Federation is most useful when schema ownership is distributed and teams need to evolve their subgraphs independently under a shared contract. @@ -118,9 +119,9 @@ schema is expected to grow. | Pattern | Best for | GraphQL.js support | Tooling required | |---|---|---|---| -| Monolith | Simpler apps and single-team ownership | Built-in | None | +| Monolith | Default choice for most projects; simpler, faster, easier to reason about | Built-in | None | | Schema stitching | Aggregating services you control | External tooling required | `@graphql-tools/stitch` -| Federation | Distributed graphs across many teams | Manual implementation | Apollo Federation or custom | +| Federation | Large enterprises; many teams contributing to a distributed graph independently | Manual implementation | Significant tooling and infrastructure | ## Migration paths From 2902a9765e41e8809cecfd24027d055a0c38c3f3 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 29 May 2025 13:24:28 +0100 Subject: [PATCH 4/4] Missing word --- cspell.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/cspell.yml b/cspell.yml index 87a25a67f9..b0add4f37d 100644 --- a/cspell.yml +++ b/cspell.yml @@ -30,6 +30,7 @@ overrides: - subschema - subschemas - NATS + - Graphile ignoreRegExpList: - u\{[0-9a-f]{1,8}\}