Introduction to Apollo Federation
Implement a single data graph across multiple services
To get the most out of GraphQL, your organization should expose a single data graph that provides a unified interface for querying any combination of your backing data sources. However, it can be challenging to represent an enterprise-scale data graph with a single, monolithic GraphQL server.
To remedy this, you can divide your graph's implementation across multiple composable services with Apollo Federation:
Unlike other distributed GraphQL architectures (such as schema stitching), Apollo Federation uses a declarative programming model that enables each implementing service to implement only the part of your graph that it's responsible for.
Apollo Federation also supports a free managed mode with Apollo Studio, which enables you to add, remove, and refactor your implementing services without requiring any downtime for your production graph.
Architecture
An Apollo Federation architecture consists of:
- A collection of implementing services that each define a distinct GraphQL schema
- A gateway that composes the distinct schemas into a federated data graph and executes queries across the services in the graph
Apollo Server provides libraries for acting both as an implementing service and as a gateway, but these components can be implemented in any language and framework.
Apollo Federation does not currently support GraphQL subscription operations.
The following presentation by Mandi Wise further describes the architecture of Apollo Federation and walks through implementing a federated graph:
Core principles
Incremental adoption
Like the rest of the Apollo platform, Apollo Federation can (and should) be adopted incrementally:
- If you currently use a monolithic GraphQL server, you can break its functionality out one service at a time.
- If you currently use a different federated architecture (such as schema stitching), you can add federation support to your existing implementing services one at a time.
In both of these cases, all of your clients will continue to work throughout your incremental migration. In fact, clients have no way to distinguish between different data graph implementations.
Separation of concerns
Apollo Federation encourages a design principle called separation of concerns. This enables different teams to work on different products and features within a single data graph, without interfering with each other.
Limitations of type-based separation
When considering how to split a single GraphQL schema across multiple services, it seems straightforward to divide schemas up by type. For example, a users
service would define the entirety of a User
type, the products
service would define a Product
type, and so on:

Although this separation looks clean, it quickly causes issues. Specifically, a particular feature (or concern) usually spans multiple types.
Consider the recentPurchases
field of the User
type in the above schema. Even though this field is a member of the User
type, a list of Product
s should probably be populated by the products
service, not the users
service.
By defining the recentPurchases
field in the products
service instead:
- The service that defines the field is also the service that knows how to populate the field. The
users
service might not even have access to the back-end data store that contains product data. - The team that manages product data can contain all product-related logic in a single service that they own unilaterally.
Concern-based separation
The following schema uses Apollo Federation to divide the same set of types and fields across the same three services:

The difference is that now, each service defines the types and fields that it is capable of (and should be responsible for) populating from its back-end data store.
The result is the best of both worlds: an implementation that keeps all the code for a given feature in a single service and separated from unrelated concerns, and a product-centric schema with rich types that reflects the natural way an application developer would want to consume the graph.
Apollo Server libraries
Apollo Server supports Apollo Federation via two open-source extension libraries:
@apollo/federation
provides primitives that your implementing services use to make their individual GraphQL schemas composable.@apollo/gateway
enables you to set up an instance of Apollo Server as a gateway that distributes incoming GraphQL operations across one or more implementing services.
Federated schema example
Let's look at an example. Below, we define the schema for a basic e-commerce application as three federated schemas, each of which is implemented as a standalone GraphQL service:
extend type Query {
me: User
}
type User @key(fields: "id") {
id: ID!
username: String!
}
extend type Query {
topProducts(first: Int = 5): [Product]
}
type Product @key(fields: "upc") {
upc: String!
name: String!
price: Int
}
type Review {
body: String
author: User @provides(fields: "username")
product: Product
}
extend type User @key(fields: "id") {
id: ID! @external
reviews: [Review]
}
extend type Product @key(fields: "upc") {
upc: String! @external
reviews: [Review]
}
These schemas illustrate several important conventions of Apollo Federation:
An implementing service can reference a type that's defined by another implementing service. For example, the
Review
type includes aproduct
field of typeProduct
, even though theProduct
type is defined in a different service.An implementing service can also extend a type that's defined by another implementing service. For example, the
reviews
service extends theUser
type by adding areviews
field to it.An implementing service must add the
@key
directive to a type's definition in order for other services to be able to reference or extend that type. This directive tells other services which fields to use to uniquely identify a particular instance of the type.
Gateway example
The gateway for our federated data graph fetches the schema from each implementing service and composes those schemas into a single graph:
const gateway = new ApolloGateway({
serviceList: [
{ name: 'accounts', url: 'http://localhost:4001' },
{ name: 'products', url: 'http://localhost:4002' },
{ name: 'reviews', url: 'http://localhost:4003' }
]
});
const server = new ApolloServer({ gateway });
server.listen();
That’s it! With Apollo Federation, schemas and resolvers live in your implementing services. The gateway serves only to plan and execute GraphQL operations across those implementing services.
Managed federation
In addition to running a gateway with a static list of services, Apollo Gateway can operate in managed federation mode, where Apollo Studio acts as the source of truth for each implementing service's schema.
This mode enables multiple teams working on a data graph to coordinate when and how underlying services change. For more information, read Managed federation overview.
Query example
Now we can execute GraphQL operations against our composed schema just as if it were implemented as a single, monolithic service:
# A query that the gateway resolves by calling all three services
query GetCurrentUserReviews {
me {
username
reviews {
body
product {
name
upc
}
}
}
}
Next, learn how to define an implementing service.