GraphQL Federation: A Practical Overview
Understand Apollo Federation: subgraphs, the gateway, entity references, and when to choose federation over a monolithic GraphQL schema.
What you'll learn
- ✓What federation solves
- ✓Subgraphs, the gateway, and the supergraph
- ✓Entity references with @key and __resolveReference
- ✓When federation is worth it
- ✓Common federation pitfalls
Prerequisites
- •Comfortable with GraphQL schemas
What and Why
A single GraphQL schema works great for one team. When many teams own different domains, the schema becomes a battleground. Federation splits it: each team runs its own subgraph, and a gateway composes them into one supergraph for clients.
Mental Model
A federated graph has three layers. Subgraphs are services that own a piece of the schema. The gateway plans and executes queries by routing field resolution to the right subgraph. Clients see one unified schema.
Client query
|
v
Gateway (router)
/ | \
Users Products Orders
subgraph subgraph subgraph
| | |
Users DB Catalog DB Orders DB Hands-on Example
Users subgraph declares the User entity.
extend schema @link(url: "https://specs.apollo.dev/federation/v2.5",
import: ["@key"])
type User @key(fields: "id") {
id: ID!
name: String!
}
type Query {
me: User
}
Orders subgraph extends User with a field it owns.
extend schema @link(url: "https://specs.apollo.dev/federation/v2.5",
import: ["@key", "@external"])
type User @key(fields: "id", resolvable: false) {
id: ID! @external
}
type Order {
id: ID!
total: Float!
user: User!
}
type Query {
myOrders: [Order!]!
}
extend type User {
orders: [Order!]!
}
Resolvers in JavaScript subgraph.
import { buildSubgraphSchema } from "@apollo/subgraph";
const typeDefs = gql`...`;
const resolvers = {
Query: { myOrders: (_, __, ctx) => ctx.orders.forUser(ctx.user.id) },
User: {
orders: (user, _, ctx) => ctx.orders.forUser(user.id),
__resolveReference: (ref, ctx) => ({ id: ref.id }),
},
};
const schema = buildSubgraphSchema({ typeDefs, resolvers });
The gateway composes subgraphs into a single endpoint. With Apollo Router, you publish each subgraph schema to a registry and the router pulls down a supergraph SDL.
# router.yaml
supergraph:
listen: 0.0.0.0:4000
include_subgraph_errors:
all: true
A client query that spans services.
query {
me {
name
orders { id total }
}
}
The router calls Users to resolve me, gets a User ref, then asks Orders to expand orders for that id.
Common Pitfalls
- Adopting federation too early. For one team, a single monolithic schema is usually simpler and faster.
- Sharing database tables across subgraphs. Each subgraph should own its data.
- Forgetting that
@keyfields are stable identifiers. Choose ids you will never change. - Letting subgraph SDLs drift. Use schema checks in CI to catch breaking changes before merge.
- Misusing
@requiresand@provides. They are powerful but easy to misuse; read the docs carefully.
Practical Tips
- Define an owner per type. Other subgraphs should
extendrather than redefine fields. - Add schema linting to enforce naming, nullability, and federation directives.
- Track operation usage so you can deprecate fields with data, not guesses.
- Run integration tests at the gateway level with representative queries that touch multiple subgraphs.
- Treat the supergraph as a product. Version it carefully; clients depend on it.
Wrap-up
Federation is the right answer when multiple teams need autonomy over their part of a unified GraphQL API. It introduces real operational cost, so use it once your team boundaries demand it. Pick clear entity owners, automate schema checks, and design subgraphs around domains, not databases, and the supergraph becomes a powerful contract for all your clients.
Related articles
- GraphQL GraphQL Caching with Apollo Client
How Apollo Client's normalized cache works, why entity IDs matter, and the patterns for cache updates, refetches, and consistent UI after mutations.
- GraphQL GraphQL Resolver Patterns Explained
Compare resolver patterns in GraphQL: thin resolvers, service layers, DataLoader batching, and error handling that scales.
- GraphQL GraphQL Subscriptions Tutorial
Add real-time data to your GraphQL API with subscriptions. Learn the transport, pubsub patterns, and a working Apollo example.
- GraphQL GraphQL vs REST Tradeoffs
An honest comparison of GraphQL and REST: where each one shines, where each one hurts, and how to choose without religion.