🚀 Understanding GraphQL Federation in Microservices Architecture


As applications grow in complexity, microservices become the go-to architectural pattern. But with them comes a new challenge: API sprawl. Each service manages its own schema, leading to a tangled mess of REST endpoints or isolated GraphQL APIs.
Enter GraphQL Federation—a powerful solution that lets you compose a unified GraphQL API from multiple microservices, while keeping each service independently developed and deployed.
In this article, we’ll break down what GraphQL Federation is, how it works, and why it’s a game-changer for modern backend systems.
🧩 What Is GraphQL Federation?
GraphQL Federation is a technique introduced by Apollo that allows multiple GraphQL services (called subgraphs) to be merged into a single, unified API gateway (called the federated gateway).
It solves a critical issue in microservice architectures: how to let teams work independently on their own GraphQL schemas, while still offering a seamless client experience through a single graph.
Key Components:
Component | Description |
Subgraph | An individual GraphQL service with part of the overall schema |
Federated Gateway | The GraphQL server that stitches all subgraphs into one unified schema |
@key Directive | Used to define the primary key for an entity shared across subgraphs |
@requires / @provides | Manage dependency fields between subgraphs |
🔍 Core Concepts Explained
1. Entity Resolution with @key
If multiple services work on the same entity (e.g., User
), the @key
directive tells the gateway how to resolve it:
type User @key(fields: "id") {
id: ID!
name: String
}
2. Service Extension with @extends
A service can add fields to an entity defined in another service:
# In the reviews subgraph
extend type User @key(fields: "id") {
id: ID!
reviews: [Review]
}
3. Gateway Composition
The gateway uses service definitions from each subgraph (via introspection or static configs) and composes them into a single schema that the client can query.
💡 Real-World Example: E-Commerce Platform
Let’s say you're building an e-commerce platform with the following services:
User Service: Manages user data.
Product Service: Manages products available in the store.
Order Service: Manages customer orders and ties users to the products they purchase.
With GraphQL Federation, each service defines its part of the schema and can extend entities from other services to build a unified graph.
🔹 Schema in User Service:
type User @key(fields: "id") {
id: ID!
name: String
email: String
}
This defines the User
entity and its primary key (id
). It can be referenced by other services.
🔹 Schema in Product Service:
type Product @key(fields: "id") {
id: ID!
name: String
price: Float
}
Each product has its own ID, name, and price.
🔹 Schema in Order Service:
type Order @key(fields: "id") {
id: ID!
quantity: Int
orderDate: String
user:User @provides(fields: "id")
product:Product @provides(fields: "id")
total: Float
}
extend type User @key(fields: "id") {
id: ID!
}
extend type Product @key(fields: "id") {
id: ID!
}
This service defines the Order
entity, and extends both User
and Product
entities to show which users placed orders and which products were purchased.
🧪 Unified Query at the Gateway:
Once the services are federated into a single gateway, clients can query them as one unified schema:
query {
orders {
id
quantity
orderDate
user {
id
name
email
}
product {
id
name
price
}
}
}
This single query fetches user details, their orders, and associated product details—even though the data is spread across three separate services.
🚦 How Federation Makes This Work
The User Service owns the
User
type.The Product Service owns the
Product
type.The Order Service stitches everything together by referencing
User
andProduct
entities using the@extends
directive.
This setup allows each team to focus on their domain, deploy independently, and still contribute to a shared graph that feels seamless to the client.
⚙️ Setting Up Apollo Federation (Simplified Steps)
To federate your services using Apollo Federation, follow these steps:
🔧 Step 1: Set Up Each Subgraph (User, Product, Order)
Each service is an independent GraphQL server using the @apollo/subgraph
package.
1.1 Install Dependencies
npm install @apollo/subgraph graphql
👤 User Service
Schema (user-schema.graphql
)
type User @key(fields: "id") {
id: ID!
name: String
email: String
}
Server Setup (index.js
)
const { ApolloServer } = require('@apollo/server');
const { buildSubgraphSchema } = require('@apollo/subgraph');
const { startStandaloneServer } = require('@apollo/server/standalone');
const gql = require('graphql-tag');
const typeDefs = gql(require('fs').readFileSync('./user-schema.graphql', 'utf-8'));
const resolvers = {
User: {
__resolveReference(user) {
return users.find(u => u.id === user.id);
},
},
};
const server = new ApolloServer({
schema: buildSubgraphSchema([{ typeDefs, resolvers }]),
});
startStandaloneServer(server, { listen: { port: 4001 } });
📦 Product Service
Schema (product-schema.graphql
)
type Product @key(fields: "id") {
id: ID!
name: String
price: Float
}
Server Setup (index.js
)
Use the same @apollo/subgraph
setup, listening on port 4002
.
📑 Order Service
This one extends both User
and Product
entities.
Schema (order-schema.graphql
)
type Order @key(fields: "id") {
id: ID!
user: User
products: [Product]
total: Float
}
extend type User @key(fields: "id") {
id: ID!
orders: [Order]
}
extend type Product @key(fields: "id") {
id: ID!
purchasedBy: [User]
}
Server Setup
Use the same @apollo/subgraph
setup, listening on port 4003
.
🛠 Step 2: Set Up Apollo Gateway
This service composes the subgraphs and exposes one unified schema.
Install Required Packages
npm install @apollo/gateway graphql @apollo/server
Gateway Setup (gateway.js
)
const { ApolloServer } = require('@apollo/server');
const { ApolloGateway } = require('@apollo/gateway');
const { startStandaloneServer } = require('@apollo/server/standalone');
const gateway = new ApolloGateway({
serviceList: [
{ name: 'user', url: 'http://localhost:4001' },
{ name: 'product', url: 'http://localhost:4002' },
{ name: 'order', url: 'http://localhost:4003' },
],
});
const server = new ApolloServer({ gateway, subscriptions: false });
startStandaloneServer(server, { listen: { port: 4000 } }).then(({ url }) => {
console.log(`🚀 Gateway ready at ${url}`);
});
🔁 Step 3: Start All Services
In separate terminal tabs or scripts:
# Terminal 1
node user/index.js
# Terminal 2
node product/index.js
# Terminal 3
node order/index.js
# Terminal 4
node gateway.js
Now your GraphQL API is live at http://localhost:4000/graphql
and unified!
🧪 Step 4: Query the Federated Schema
Test it with a powerful, nested query:
query {
orders {
id
quantity
orderDate
user {
id
name
email
}
product {
id
name
price
}
}
}
Even though user
, order
, and product
are handled by separate microservices, this single query works flawlessly via federation!
⚖️ Pros and Cons of Using GraphQL Federation
Before adopting GraphQL Federation in your architecture, it’s important to weigh its advantages and potential challenges. Here’s a balanced look:
✅ Pros of GraphQL Federation
Benefit | Description |
Modular Architecture | Each subgraph service is owned and maintained by individual teams. This promotes autonomy and scalability. |
Single Unified Graph | The client interacts with one clean, unified API—regardless of how many services are involved behind the scenes. |
Independent Deployment | Subgraphs can be deployed independently without needing to rebuild or restart the gateway or other services. |
Schema Collaboration | Teams can contribute to shared entities (e.g., User , Product ) using directives like @extends and @key , enabling tight yet controlled coupling. |
Optimized Developer Experience | Great tools from Apollo like Rover , schema registry, and schema checks make collaboration and CI/CD smooth. |
Frontend Simplicity | Frontend developers can query complex relationships in a single request, improving developer productivity and reducing over-fetching. |
⚠️ Cons of GraphQL Federation
Limitation | Description |
Increased Operational Complexity | Managing multiple subgraph services and the gateway adds overhead to DevOps and deployment pipelines. |
Cross-Team Coordination | Schema design requires coordination across teams when extending shared entities, especially in larger orgs. |
Performance Bottlenecks | Poorly designed federated queries can result in N+1 problems or excessive network calls between services. Caching and batching become more critical. |
Learning Curve | Developers must understand GraphQL directives (@key , @extends , etc.), entity resolution, and subgraph architecture. |
Debugging Can Be Tricky | When things break, it can be harder to trace errors across subgraphs and the gateway. |
Gateway is a Single Point of Failure | Unless properly scaled and load-balanced, the Apollo Gateway can become a bottleneck or SPOF (single point of failure). |
🧠 When to Use GraphQL Federation
Use Federation when:
You have multiple teams working on different domains (e.g., user, orders, products).
You want to avoid monolithic GraphQL servers.
You’re already on a microservices architecture and need a clean API layer.
You need to enable schema composition and controlled entity extension.
Avoid Federation when:
You have a small team or a small monolithic app.
Your microservices don't share much schema or are loosely coupled.
You’re not familiar with GraphQL or don’t have time to invest in tooling/setup.
🎯 Conclusion: Future-Proof Your Backend
GraphQL Federation brings structure, scalability, and clarity to the chaos of microservice APIs. It aligns perfectly with the modular development goals of backend teams, while keeping the developer experience smooth on both server and client ends.
If you're building a microservices architecture or already using GraphQL, federation is worth exploring—especially with tools like Apollo Federation leading the way.
👉 Ready to federate your GraphQL APIs?
Start small—break one schema into subgraphs and try running a gateway locally. You’ll see the power of Federation in action.
Don’t forget to share this post with your team and bookmark it for reference!
Subscribe to my newsletter
Read articles from Gaurav Kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Gaurav Kumar
Gaurav Kumar
Hey! I'm Gaurav, a tech writer who's all about MERN, Next.js, and GraphQL. I love breaking down complex concepts into easy-to-understand articles. I've got a solid grip on MongoDB, Express.js, React, Node.js, and Next.js to supercharge app performance and user experiences. And let me tell you, GraphQL is a game-changer for data retrieval and manipulation. I've had the opportunity to share my knowledge through tutorials and best practices in top tech publications. My mission? Empowering developers and building a supportive community. Let's level up together with my insightful articles that'll help you create top-notch applications!