GraphQL Schema Stitching
Schema stitching combines multiple separate GraphQL schemas into one unified schema. Clients query a single endpoint and receive data that may come from several different services, each with its own schema. The stitching layer merges them transparently.
The Problem Schema Stitching Solves
Without stitching — clients talk to many servers:
──────────────────────────────────────────────────
Client ──► Users Service (localhost:4001/graphql)
Client ──► Orders Service (localhost:4002/graphql)
Client ──► Products Service (localhost:4003/graphql)
(Client manages 3 connections)
With stitching — one gateway for everything:
─────────────────────────────────────────────
Client ──► Gateway (localhost:4000/graphql)
│
├──► Users Service (internal)
├──► Orders Service (internal)
└──► Products Service (internal)
(Client sees one endpoint, one schema)
Basic Schema Stitching with @graphql-tools
npm install @graphql-tools/stitch @graphql-tools/wrap graphql
import { stitchSchemas } from '@graphql-tools/stitch';
import { buildSchema } from 'graphql';
// Schema A — Users
const usersSchema = buildSchema(`
type User {
id: ID!
name: String!
}
type Query {
user(id: ID!): User
}
`);
// Schema B — Orders
const ordersSchema = buildSchema(`
type Order {
id: ID!
total: Float!
userId: ID!
}
type Query {
order(id: ID!): Order
ordersByUser(userId: ID!): [Order]
}
`);
// Stitch them together
const gatewaySchema = stitchSchemas({
subschemas: [
{ schema: usersSchema },
{ schema: ordersSchema },
]
});
Linking Types Across Schemas
The real power of stitching comes from linking types across schemas. You extend the User type from the users schema to include orders from the orders schema. The gateway resolves the link automatically.
Type merging — User gets an orders field:
──────────────────────────────────────────
const gatewaySchema = stitchSchemas({
subschemas: [
{ schema: usersSchema },
{ schema: ordersSchema },
],
typeDefs: `
extend type User {
orders: [Order]
}
`,
resolvers: {
User: {
orders: {
selectionSet: '{ id }',
resolve: (user, _args, _context, info) => {
return delegateToSchema({
schema: ordersSchema,
operation: 'query',
fieldName: 'ordersByUser',
args: { userId: user.id },
info,
});
}
}
}
}
});
Client can now query across both services:
────────────────────────────────────────────
{
user(id: "u5") {
name ← from Users Service
orders { ← from Orders Service, linked by userId
id
total
}
}
}
Schema Stitching vs Federation
Schema Stitching Federation (Apollo) ──────────────── ─────────────────── Managed centrally Each service owns its type Gateway does the merging Services annotate with @key Services need no changes Services use federation spec More control at gateway Better for large org teams Easier to start Better for scale
When to Use Schema Stitching
Use schema stitching when you have existing GraphQL services that you cannot modify, when you want to merge third-party GraphQL APIs, or when you need a lightweight gateway without adopting the full Apollo Federation specification.
Key Points
- Schema stitching merges multiple GraphQL schemas into one unified schema at a gateway.
- Clients see one endpoint and one schema regardless of how many services sit behind it.
- Type merging extends types from one schema with fields resolved by another service.
- Stitching works well for combining existing services; Federation is better for large distributed teams.
