GraphQL Federation Pattern
Compose a unified GraphQL API from independently deployed subgraph services using Apollo Federation
When to Use
- Multiple teams own different domains and need independent deployment
- A monolithic GraphQL schema has grown too large for one service
- You need to extend types across service boundaries (e.g., adding
orderstoUserfrom the orders service) - Migrating from schema stitching to a standards-based composition model
Instructions
- Each subgraph owns its domain types. The users service defines
User, the orders service definesOrder. No type is defined in two places — types are extended across boundaries.
# users subgraph
type User @key(fields: "id") {
id: ID!
name: String!
email: String!
}
type Query {
user(id: ID!): User
}
Use
@keyto mark entity types. An entity is a type that can be referenced and extended by other subgraphs. The@keydirective specifies which fields uniquely identify the entity.Extend entities in other subgraphs with stub types. The orders service references
Userwithout redefining it — it provides only the key field and adds new fields.
# orders subgraph
type User @key(fields: "id") {
id: ID!
orders: [Order!]!
}
type Order @key(fields: "id") {
id: ID!
total: Money!
status: OrderStatus!
customer: User!
}
- Implement
__resolveReferencefor each entity. This resolver is called by the gateway when it needs to hydrate a stub entity. It receives the key fields and returns the full object.
const resolvers = {
User: {
__resolveReference: (ref: { id: string }, { dataSources }) => {
return dataSources.users.findById(ref.id);
},
},
};
- Use the Apollo Router (or Gateway) to compose subgraphs. The router fetches schemas from each subgraph, composes them into a supergraph, and routes incoming queries to the appropriate subgraphs.
# supergraph-config.yaml
subgraphs:
users:
routing_url: http://users-service:4001/graphql
schema:
subgraph_url: http://users-service:4001/graphql
orders:
routing_url: http://orders-service:4002/graphql
schema:
subgraph_url: http://orders-service:4002/graphql
Use
@shareablefor fields that multiple subgraphs can resolve. In Federation v2, fields are exclusive by default. Mark fields@shareablewhen multiple subgraphs need to return the same field.Use
@overrideto migrate fields between subgraphs. When moving a field from one subgraph to another, the new owner uses@override(from: "old-subgraph")to claim resolution without a breaking change.Use
@external,@provides, and@requiresfor computed fields.@requirestells the gateway to fetch specified fields from the owning subgraph before calling the current resolver.
# shipping subgraph
type Order @key(fields: "id") {
id: ID!
weight: Float @external
shippingCost: Float @requires(fields: "weight")
}
Run composition checks in CI. Use
rover subgraph checkto validate that schema changes in one subgraph do not break the composed supergraph before deploying.Keep the gateway stateless. The router/gateway should not contain business logic — it composes and routes. All business logic lives in subgraphs.
Details
Federation v1 vs. v2: Federation v2 (current) uses @link to import federation directives, supports @shareable, @override, @inaccessible, and progressive @override for safe migrations. Prefer v2 for new projects.
Query planning: The gateway decomposes incoming queries into subgraph fetches. A query for user { name orders { total } } fetches name from the users subgraph, then fetches orders from the orders subgraph using the user's id as the reference key. This happens transparently.
Performance considerations:
- Entity references add network hops — the gateway calls
__resolveReferenceon the owning subgraph - Use
@providesto return extra fields alongside entities to reduce follow-up fetches - Batch entity lookups in
__resolveReferenceusing DataLoader
Ownership rules:
- A type's
@keyfields must be resolvable by the defining subgraph - Only one subgraph should define a field (unless
@shareable) - Value types (types without
@key) must be identical across subgraphs
Common mistakes:
- Circular entity references that cause infinite gateway loops
- Missing
__resolveReference— the gateway cannot hydrate the entity - Changing
@keyfields without updating all referencing subgraphs - Putting too many types in one subgraph, recreating the monolith
Source
https://www.apollographql.com/docs/federation/
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.