66 Introduction to Federated GraphQL Architecture
66 Introduction to Federated GraphQL Architecture
GraphQL continues to be a popular choice for designing modern APIs, largely thanks to its ability to reduce over-fetching and under-fetching while providing a consistent API surface for a variety of clients. However, as the demands of scale and system complexity grow, one fundamental challenge emerges: how do you manage many microservice domains that you want to expose through a single, centralized GraphQL endpoint? This is exactly where the concept of Federated GraphQL Architecture, popularized by Apollo, becomes a cutting-edge solution.
This article explores the concept of Federated GraphQL architecture, why it matters for scaling microservices, and a simple simulation of how to implement it—including code examples and flow diagrams to make the architecture clearer.
Why Do You Need Federation?
For small to medium-sized applications, the traditional GraphQL architecture—a single schema and a single server—is effective enough. But as an application grows and teams begin adopting microservices, the single-schema approach becomes a bottleneck. Here are the problems that frequently arise:
| Problem | Impact on a Single GraphQL Server |
|---|---|
| Growing schema | Hard for a single team to maintain |
| Hindered deployments | Every update must be synchronized to the schema |
| Scalability | Limited ability to scale per domain logic |
| Ownership | No single team can be the full owner |
Example: the “User” and “Product” teams want to develop their APIs with their own timelines and deployment cadences. If schemas and resolvers are confined to a single GraphQL monolith, ownership and scaling conflicts are almost guaranteed.
Entering Federated Architecture
Apollo Federation introduces a distributed schema composition approach. Each domain service defines its own GraphQL schema along with its own resolvers. A “gateway” then dynamically combines them into a single supergraph that is exposed to clients.
Core components of Federation:
Subgraph Service
A microservice with its own GraphQL schema and resolvers, such as User and Product.Apollo Gateway
A service that combines all subgraphs into a single, unified GraphQL endpoint.
A simple flow diagram of the system:
flowchart LR
Client --> Gateway
Gateway --> UserService
Gateway --> ProductService
Core Federation Concepts
There are three key concepts:
- @key: Marks an entity’s identity within the schema, for example
id. - @extends and @external**: Used to extend a type across subgraphs.
- Joins: Automatic joins between subgraphs performed by the gateway.
An example using the User and Product domains:
user-service/schema.graphql
1type User @key(fields: "id") {
2 id: ID!
3 name: String!
4 email: String!
5}
6type Query {
7 me: User
8}product-service/schema.graphql
1type Product @key(fields: "upc") {
2 upc: String!
3 name: String!
4}
5
6extend type User @key(fields: "id") {
7 id: ID! @external
8 purchasedProducts: [Product]
9}In the example above, the product-service schema extends the User entity and can attach a new field called purchasedProducts to User, even though User originally lives in a different service.
Building the Gateway
Here is an example of an Apollo Gateway that combines the two subgraphs:
1// index.js
2const { ApolloServer } = require('@apollo/server');
3const { ApolloGateway } = require('@apollo/gateway');
4
5const gateway = new ApolloGateway({
6 serviceList: [
7 { name: 'user', url: 'http://localhost:4001/graphql' },
8 { name: 'product', url: 'http://localhost:4002/graphql' },
9 ],
10});
11
12const server = new ApolloServer({
13 gateway,
14 // Disable subscriptions and introspection for gateway server
15 subscriptions: false,
16 playground: true,
17});
18
19server.listen({ port: 4000 }).then(({ url }) => {
20 console.log(`Gateway ready at ${url}`);
21});With the configuration above, you simply run three services in parallel:
- user-service on port 4001
- product-service on port 4002
- gateway on port 4000
Every query sent to the gateway is automatically distributed to the respective services by federation.
End-to-End Query Simulation
A client can run a query like this:
1query {
2 me {
3 id
4 name
5 purchasedProducts {
6 upc
7 name
8 }
9 }
10}The gateway will:
- Request the
medata from user-service. - Then, using the user’s
id, request thepurchasedProductsdata from product-service.
An illustration of the query flow through the Federation Gateway:
sequenceDiagram
participant Client
participant Gateway
participant UserService
participant ProductService
Client->>Gateway: Query { me { id name purchasedProducts { upc name } } }
Gateway->>UserService: Query { me { id name } }
UserService-->>Gateway: Response { me: { id, name } }
Gateway->>ProductService: Query { user(id) { purchasedProducts { ... } } }
ProductService-->>Gateway: Response { purchasedProducts }
Gateway-->>Client: Aggregate Response
Comparison With Stitched Schemas
Before Federation, another popular architecture was “schema stitching,” which manually combined GraphQL schemas in middleware. Federation offers several advantages:
| Schema Stitching | Federated Architecture | |
|---|---|---|
| Dynamic Composition | Difficult, requires manual adaptation | Automatic, handled by the gateway |
| Domain Ownership | Unclear | Strong boundaries per service |
| Extensibility | Hard to extend entities | Can extend via @extends & @external |
| Maintainability | Frequent conflicts | More modular & scalable |
Pros and Cons
Pros:
- Isolation of schemas and resolvers per team/domain.
- Automated joins and schema composition.
- Microservices can be deployed independently.
- A rich tooling ecosystem (Apollo Studio, gateway, tracing, and more).
Cons:
- The initial learning curve is fairly steep.
- If the gateway goes down, all subgraphs are affected.
- Tracing and observability overhead is more complex.
- Inter-service security requires special attention.
Conclusion
Federated GraphQL Architecture is the answer to the need for modern, modular, and scalable APIs in the microservices era. By splitting the schema into subgraphs with a single gateway as the distributed entry point, ownership and deployment for each domain become clearer, and API management becomes far more flexible.
Getting a team comfortable with Federation does take time, but for applications whose domains keep growing and require scalability, this architecture is an investment well worth making.
Further Reading:
Try federation on your own services and feel the difference!