Apollo Federation Microservices with Unified GraphQL
Introduction
Apollo Federation is a modern approach to building scalable GraphQL architectures by combining multiple microservices into a single unified GraphQL API—often called a supergraph. Instead of maintaining one large monolithic schema, you split your backend into smaller services (subgraphs), each responsible for a specific domain like users, products, or orders.
In this apollo federation tutorial, you’ll learn how to design and implement GraphQL microservices using federation, and how to stitch them together seamlessly using an Apollo Router or Gateway.
For Pakistani students and developers, this approach is highly relevant. Many startups in cities like Lahore, Karachi, and Islamabad are moving toward microservices to scale their systems. Whether you're building an e-commerce platform where Ahmad manages products and Fatima handles users, or a fintech system dealing with PKR transactions, graphql federation helps you organize your backend efficiently.
Prerequisites
Before diving into this advanced tutorial, you should be comfortable with:
- Basic GraphQL concepts (queries, mutations, resolvers)
- Node.js and JavaScript (or TypeScript)
- REST vs GraphQL differences
- Express.js or similar backend frameworks
- Understanding of microservices architecture
- Familiarity with npm/yarn and CLI tools
If you’re new, consider first studying a GraphQL tutorial and microservices basics.
Core Concepts & Explanation
Subgraphs and the Supergraph
In Apollo Federation, each microservice exposes a subgraph schema. These subgraphs are combined into a supergraph schema that clients interact with.
Example:
- Users Service → handles user data
- Products Service → handles product data
- Orders Service → connects users and products
Each service defines its own schema, and Apollo merges them.
# Users Subgraph
type User @key(fields: "id") {
id: ID!
name: String
city: String
}
Explanation:
type User→ defines a GraphQL type@key(fields: "id")→ marksidas the unique identifier for federationname,city→ user-specific fields
Entity Resolution and @key Directive
The @key directive allows different services to reference the same entity.
type Product @key(fields: "id") {
id: ID!
name: String
price: Int
}
Now suppose Orders service wants to link users and products:
type Order {
id: ID!
user: User
product: Product
}
To resolve references across services, we use __resolveReference.
User: {
__resolveReference(reference) {
return users.find(user => user.id === reference.id);
}
}
Explanation:
reference→ contains entity key (id)users.find(...)→ fetch actual data- Returns full entity to the gateway

Practical Code Examples
Example 1: Building a Users Subgraph
Let’s build a simple Users service using Node.js.
// Step 1: Import dependencies
const { ApolloServer } = require('@apollo/server');
const { startStandaloneServer } = require('@apollo/server/standalone');
const { buildSubgraphSchema } = require('@apollo/subgraph');
const gql = require('graphql-tag');
// Step 2: Define schema
const typeDefs = gql`
type User @key(fields: "id") {
id: ID!
name: String
city: String
}
type Query {
users: [User]
}
`;
// Step 3: Sample data
const users = [
{ id: "1", name: "Ahmad", city: "Lahore" },
{ id: "2", name: "Fatima", city: "Karachi" }
];
// Step 4: Define resolvers
const resolvers = {
Query: {
users: () => users
},
User: {
__resolveReference(ref) {
return users.find(user => user.id === ref.id);
}
}
};
// Step 5: Create server
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers })
});
// Step 6: Start server
startStandaloneServer(server, { listen: { port: 4001 } });
Line-by-line Explanation:
require('@apollo/server')→ imports Apollo ServerbuildSubgraphSchema→ converts schema into a federated subgraphtypeDefs→ defines GraphQL schemausers→ mock databaseQuery.users→ returns all users__resolveReference→ resolves federated referencesApolloServer→ creates server instancestartStandaloneServer→ runs the server on port 4001
Example 2: Real-World Application (E-commerce Federation)
Let’s simulate a Pakistani e-commerce system:
// Products Subgraph
const typeDefs = gql`
type Product @key(fields: "id") {
id: ID!
name: String
price: Int
}
type Query {
products: [Product]
}
`;
const products = [
{ id: "101", name: "Laptop", price: 150000 },
{ id: "102", name: "Mobile", price: 50000 }
];
const resolvers = {
Query: {
products: () => products
},
Product: {
__resolveReference(ref) {
return products.find(p => p.id === ref.id);
}
}
};
Explanation:
- Defines Product entity with
@key - Stores prices in PKR (real-world relevance)
- Resolver returns product list
- Federation resolver connects services
Now, the Apollo Router combines services:
# router.yaml
supergraph:
listen: 0.0.0.0:4000
Explanation:
supergraph.listen→ defines gateway port- Router forwards queries to subgraphs automatically

Common Mistakes & How to Avoid Them
Mistake 1: Missing @key Directive
Problem:
Without @key, federation cannot identify entities.
type User {
id: ID!
name: String
}
Fix:
type User @key(fields: "id") {
id: ID!
name: String
}
Why it matters:
Federation needs a unique identifier to connect services.
Mistake 2: Incorrect Reference Resolver
Problem:
__resolveReference(ref) {
return null;
}
This breaks data fetching.
Fix:
__resolveReference(ref) {
return users.find(u => u.id === ref.id);
}
Why it matters:
If reference resolution fails, your supergraph returns incomplete data.

Practice Exercises
Exercise 1: Add Orders Service
Problem:
Create an Orders service linking Users and Products.
Solution:
type Order {
id: ID!
user: User
product: Product
}
const orders = [
{ id: "5001", user: { id: "1" }, product: { id: "101" } }
];
Explanation:
- Uses references (
id) instead of full objects - Federation resolves actual data from other services
Exercise 2: Extend User Type
Problem:
Add email field to User from another service.
Solution:
extend type User @key(fields: "id") {
id: ID! @external
email: String
}
Explanation:
extend type→ adds fields from another service@external→ indicates field is owned elsewhere- Enables modular schema design
Frequently Asked Questions
What is Apollo Federation?
Apollo Federation is a system for building a single GraphQL API from multiple microservices. It allows teams to work independently while still exposing a unified schema.
How do I connect multiple GraphQL services?
You define subgraphs with @key directives and use an Apollo Router or Gateway to compose them into a supergraph.
Is Apollo Federation better than schema stitching?
Yes, federation is more scalable and structured. It provides better tooling, type safety, and performance compared to older schema stitching methods.
Can I use Apollo Federation in small projects?
You can, but it’s most beneficial for medium to large systems. For small apps, a single GraphQL server is often simpler.
How do I deploy federated services?
Each subgraph is deployed independently (e.g., on AWS, Vercel, or local servers), while the router acts as a central entry point.
Summary & Key Takeaways
- Apollo Federation enables scalable GraphQL microservices architecture
- Subgraphs define independent services, combined into a supergraph
@keyand__resolveReferenceare core to entity sharing- Apollo Router handles query planning and execution
- Ideal for real-world apps like e-commerce, fintech, and SaaS in Pakistan
- Encourages modular, team-friendly backend development
Next Steps & Related Tutorials
To deepen your understanding, explore these related tutorials on theiqra.edu.pk:
- Learn the fundamentals in our GraphQL Tutorial for Beginners
- Understand system design in Microservices Architecture Guide
- Master API communication with REST vs GraphQL Comparison
- Build scalable backends with Node.js Backend Development Tutorial
These will help you transition from beginner to advanced GraphQL developer and confidently build production-ready systems.
Test Your Python Knowledge!
Finished reading? Take a quick quiz to see how much you've learned from this tutorial.