Enterprise Java
Beyond REST: GraphQL Federation in Spring Boot: Build Scalable APIs with Apollo
While REST has long dominated API design, GraphQL Federation is emerging as a powerful alternative for scalable, type-safe microservices architectures. Unlike monolithic GraphQL APIs, federation allows teams to:
✔ Decouple services while maintaining a unified GraphQL schema
✔ Avoid overfetching/underfetching (common in REST)
✔ Scale independently without breaking clients
In this guide, we’ll implement a federated GraphQL API using:
- Spring Boot (Java backend)
- Apollo Federation (schema stitching)
- Apollo Gateway (query routing)
1. Why Federation? Problems with REST & Monolithic GraphQL
The Limits of REST in Microservices
| Issue | REST | Federated GraphQL |
|---|---|---|
| Overfetching | Common (fixed responses) | Clients query only what they need |
| Versioning | /v1, /v2 endpoints | Single evolving schema |
| Service Coupling | Tight integration (Swagger hell) | Autonomous services |
Monolithic GraphQL’s Scaling Issues
A single GraphQL server becomes:
- A bottleneck (all teams modify the same schema)
- Hard to deploy (one change requires full redeploy)
Solution: Federation splits the schema across services.
2. Federated Architecture Overview
┌─────────────────┐
│ Apollo │
│ Gateway │
└───────┬───────┘
│ Routes queries
┌─────────────────┼─────────────────┐
│ │ │
┌──────────▼─────┐ ┌────────▼──────┐ ┌────────▼──────┐
│ User Service │ │ Order Service│ │ Product │
│ (Spring Boot) │ │ (Spring Boot)│ │ Service │
└────────────────┘ └───────────────┘ └──────────────┘
Key Components:
- Subgraph Services (Spring Boot +
@Keydirectives) - Apollo Gateway (merges schemas + routes queries)
3. Implementing a Federated User Service in Spring Boot
Step 1: Add Dependencies (pom.xml)
<dependency>
<groupId>com.apollographql.federation</groupId>
<artifactId>federation-graphql-java-support</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
Step 2: Define a Federated Entity
// User.java
@Node // Apollo Federation's @Key directive
public class User {
@Id
private String id;
private String username;
// ... getters
}
Step 3: Extend the Schema with @external & @requires
# schema.graphqls
type User @key(fields: "id") {
id: ID!
username: String!
orders: [Order] @external
}
extend type Order @key(fields: "id") {
id: ID! @external
buyer: User @requires(fields: "id")
}
Step 4: Resolve Federated Fields
@QueryMapping
public User user(@Argument String id) {
return userRepo.findById(id);
}
@SchemaMapping
public User buyer(Order order) {
return userClient.getUser(order.getBuyerId()); // REST call to Order Service
}
4. Apollo Gateway Setup
Config (gateway.yaml)
services:
user-service:
url: http://localhost:8081/graphql
order-service:
url: http://localhost:8082/graphql
Starting the Gateway
npx apollo-server@latest gateway --config ./gateway.yaml
Now, clients query the gateway, which:
- Stitches schemas from all services
- Routes queries to the right subgraph
5. Performance & Caching Considerations
Optimizing Federated Queries
@requires→ Batch data fetches (avoid N+1)- DataLoader → Cache subgraph responses
- Subgraph-level caching (Redis, Caffeine)
Monitoring
- Apollo Studio → Track query performance
- Distributed tracing (Zipkin, Jaeger)
6. When to Choose Federation Over REST
| Use Case | REST | GraphQL Federation |
|---|---|---|
| Mobile-heavy apps | High latency | Single query |
| Microservices | Versioning hell | Schema stitching |
| Legacy migration | Easy | Incremental adoption |
Conclusion: Is Federation Worth It?
Best for:
- Large-scale microservices
- Teams needing autonomy + unified APIs
- Mobile/SPA clients
Avoid if:
- Your API is simple (REST suffices)
- You lack GraphQL expertise
Next Steps:
Federation lets you scale GraphQL without monolithic pain. Try it!




