Introduction to Apollo Federation
Combine GraphQL APIs into a unified supergraph
📣 Apollo Federation 2 is generally available!
Docs for Federation 1 are available here.
Apollo Federation is a powerful, open architecture for creating a supergraph that combines multiple GraphQL APIs:
With federation, you can responsibly share ownership of your supergraph across any number of teams. And even if you currently only have one GraphQL API, Apollo Federation is essential for scaling that API as you grow your features, user base, and organization.
Federation also supports a free managed mode with Apollo Studio, which helps you modify and grow your supergraph without any downtime.
How it works
In a federated architecture, your individual GraphQL APIs are called subgraphs, and they're composed into a supergraph. By querying your supergraph, clients can query all of your subgraphs at the same time:
A graph router (also known as a gateway) serves as the public access point for your supergraph. It receives incoming GraphQL operations and intelligently routes them across your subgraphs. To clients, this looks exactly the same as querying any other GraphQL server—no client-side configuration is required.
Apollo Federation does not currently support GraphQL subscription operations.
Combining subgraph schemas
Like any other GraphQL API, each subgraph has its own schema:
type User {id: ID!name: String!}
type Product {upc: String!inStock: Boolean!}
To communicate with all of your subgraphs, the router uses a special supergraph schema that combines these subgraph schemas.
To create a supergraph schema, you use a process called composition. Composition takes all of your subgraph schemas and intelligently combines them into one schema for your router:
type User {id: ID!name: String!}type Product {upc: String!inStock: Boolean!}
A real supergraph schema includes additional information that tells your router which subgraph is responsible for which types and fields. Learn more about composition.
Server instances
In a federated architecture, each subgraph instance has its own GraphQL server, and so does the router. External clients query the router, and the router then queries individual subgraphs to obtain, combine, and return results:
- The router is one of the following:
- An instance of the Apollo Router: a high-performance, precompiled Rust executable
- An instance of Apollo Server using special extensions from the
@apollo/gateway
library
- Subgraphs can run Apollo Server using special extensions from the
@apollo/subgraph
library, or they can run any other subgraph-compatible GraphQL server. Different subgraphs in the same supergraph can even use different server libraries.
Benefits of federation
Unify your graph
Often when an organization first adopts GraphQL, multiple teams do so independently. Each team sets up a GraphQL server that provides the data used by that team:
❌
But with an architecture like this, a client might need to communicate with multiple APIs to fetch all of the data it needs. This diminishes a powerful advantage of GraphQL over REST.
Instead, your organization should expose a unified supergraph that lets clients fetch all of the data that they need from a single endpoint:
✅
By unifying your supergraph with Apollo Federation, teams can continue to own and develop their subgraphs independently, and clients can fetch data from all of those subgraphs with a single query.
Break up monolithic code
It can be challenging to represent an entire enterprise-scale graph with a monolithic GraphQL server. Performance might degrade as your users and features increase, and teams across your organization are all committing changes to the same application:
❌
With a supergraph, you can reduce performance and productivity bottlenecks simultaneously. Each team can maintain their own subgraph(s) independently, and your supergraph's router serves primarily to route incoming operations, not to resolve each of them completely.
✅
In this structure, the "graph team" might be a separate team that's dedicated to maintaining your router as part of back-end infrastructure, or it might be a "meta team" that includes representatives from other teams that maintain subgraphs.
Adopt incrementally
As with the rest of the Apollo platform, you can (and should) adopt Apollo Federation incrementally:
- If you currently use a monolithic GraphQL server, you can break its functionality out one subgraph at a time.
- If you currently use a different federated architecture (such as schema stitching), you can add federation support to your existing services one at a time.
In both of these cases, all of your clients continue to work throughout your incremental adoption. In fact, clients have no way to distinguish between different 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 graph, without interfering with each other.
Limitations of type-based separation
When thinking about how to divide your graph's functionality across subgraphs, it might initially seem logical for each subgraph to own a completely distinct set of types. For example, a Users subgraph would define the entirety of a User
type, the Products subgraph would define a Product
type, and so on:
❌
type User {id: ID!name: Stringreviews: [Review]purchases: [Product]}
type Product {id: ID!name: Stringprice: Stringreviews: [Review]}
type Review {id: ID!body: Stringauthor: Userproduct: Product}
Although this separation looks clean, it quickly causes issues. Most commonly, a particular feature (or concern) usually spans multiple types, which might belong to different subgraphs.
Consider the User.purchases
field above. Even though this field belongs to the User
type, a list of Product
s should probably be populated by the Products subgraph, not the Users subgraph.
By defining the User.purchases
field in the Products subgraph instead:
- The subgraph that defines the field is also the subgraph that knows how to populate the field. The Users subgraph 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 subgraph that they are responsible for.
Concern-based separation
The following schema uses Apollo Federation to divide the same set of types and fields across the same three subgraphs:
Some federation-specific syntax is omitted here for clarity. For details, see Entities.
✅
type User {id: ID!name: String}
type Product {id: ID!name: Stringprice: String}type User {id: ID!purchases: [Product]}
type Review {id: ID!body: Stringauthor: Userproduct: Product}type User {id: ID!reviews: [Review]}type Product {id: ID!reviews: [Review]}
The difference is that now, each subgraph mostly defines types and fields that it is capable of (and should be responsible for) populating from its back-end data store.
You'll notice some exceptions to this, such as Review.product
(which is still defined in the Reviews subgraph even though it requires data from the Products subgraph). Exceptions like this improve data encapsulation (the Products subgraph doesn't really need to know about the Review
type), and we handle them with powerful federated types called entities.
These resulting schemas provide the best of both worlds:
- An implementation that keeps the code for a given feature in a single subgraph and separated from unrelated concerns
- A product-centric schema with rich types that reflect the natural way an application developer wants to consume the graph
Managed federation
A graph router can operate in managed federation mode, where Apollo Studio acts as the source of truth for your supergraph's configuration:
This mode helps multiple teams working on a supergraph to coordinate when and how to change individual subgraphs. It's recommended for all supergraphs. For more information, read Managed federation overview.
Ready to try out Apollo Federation? Jump into the Quickstart!