Home/Learn/Microservices/GraphQL as an API Layer

GraphQL as an API Layer

Advanced
Communication

GraphQL aggregates data from multiple microservices in a single query, reducing over-fetching and under-fetching; ideal for flexible client-driven data requirements.

Overview

In a microservices architecture, GraphQL is often placed at the API gateway layer as a federated aggregation point. Instead of clients making multiple REST calls to different services (order service, customer service, product service) and stitching data together, a single GraphQL query traverses resolvers that fan out to the appropriate downstream services. Spring for GraphQL (spring-boot-starter-graphql) provides schema-first development with annotated controllers, DataLoader integration for batching/caching, and subscriptions over WebSocket. Apollo Federation takes this further by letting each microservice own part of the schema, which the gateway then composes into a unified supergraph.

Spring for GraphQL — Schema and Controller

Define the schema in .graphqls files under src/main/resources/graphql/. Map query fields to @QueryMapping methods; use @SchemaMapping for nested type resolvers that call downstream services.

Java — Spring for GraphQL schema + resolvers
# schema.graphqls
type Query {
    order(id: ID!): Order
}
type Order {
    id: ID!
    status: String!
    customer: Customer   # resolved by CustomerService
    items: [OrderItem!]! # resolved by ProductService
}

@Controller
public class OrderController {

    @QueryMapping
    public Order order(@Argument Long id) {
        return orderService.findById(id);
    }

    @SchemaMapping(typeName = "Order", field = "customer")
    public Customer customer(Order order) {
        return customerClient.findById(order.getCustomerId()); // HTTP / gRPC call
    }
}

DataLoader — Solving N+1

When a list of orders each resolves a customer, the naive approach makes N HTTP calls. DataLoader batches all keys collected during a single execution tick into one call, then caches results within the request.

Java — DataLoader for N+1 prevention
@Component
public class CustomerDataLoader implements BatchLoaderWithContext<Long, Customer> {

    @Override
    public CompletionStage<List<Customer>> load(List<Long> ids, BatchLoaderEnvironment env) {
        return CompletableFuture.supplyAsync(() ->
            customerClient.findAllByIds(ids)); // single batch call
    }
}

// In resolver — DataLoader is auto-registered by Spring for GraphQL
@SchemaMapping(typeName = "Order", field = "customer")
public CompletableFuture<Customer> customer(Order order, DataLoader<Long, Customer> loader) {
    return loader.load(order.getCustomerId()); // batched automatically
}

Apollo Federation — Distributed Schema

With Apollo Federation each service defines its own partial schema and implements a reference resolver. The Apollo Router (or Gateway) stitches subgraphs into a unified API. Services extend types owned by other services using @key and @extends.

GraphQL SDL — Apollo Federation subgraph definitions
# order-service subgraph schema
type Order @key(fields: "id") {
    id: ID!
    status: String!
    customerId: ID!
}

# customer-service subgraph extends Order
extend type Order @key(fields: "id") {
    id: ID! @external
    customer: Customer @requires(fields: "customerId")
}

# The Apollo Router composes both into one supergraph:
# query { order(id: "1") { status customer { name email } } }

Key Points to Remember

  • 1GraphQL eliminates over-fetching (too many fields) and under-fetching (too many round trips)
  • 2Spring for GraphQL uses annotated controllers + schema-first .graphqls files
  • 3DataLoader batches N resolver calls into one bulk fetch to prevent the N+1 problem
  • 4Subscriptions over WebSocket enable real-time data push from GraphQL resolvers
  • 5Apollo Federation lets each microservice own its schema slice; the gateway composes them
  • 6GraphQL is not always better than REST — use it when clients have highly variable data needs

Interview Questions

Sign in to ask Aria
1

What is the N+1 problem in GraphQL and how does DataLoader solve it?

HardNetflix
2

What is the difference between a Query, Mutation, and Subscription in GraphQL?

EasyTCS
3

How does Apollo Federation distribute the GraphQL schema across microservices?

HardAtlassian
4

When would you choose GraphQL over REST for a microservices API layer?

MediumAmazon
5

How do @SchemaMapping and @QueryMapping differ in Spring for GraphQL?

MediumInfosys

Ask Aria about GraphQL as an API Layer

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…