Skip to content
Techsense Developers
TrustLet's Talk
Insights
Software & Platform7 min readAug 31, 2026

What Is GraphQL Federation and How Does It Unify Microservices APIs?

If you run more than a handful of microservices, you have probably hit the same wall we have: each team ships its own API, clients have to stitch together data from five or six endpoints, and every…

If you run more than a handful of microservices, you have probably hit the same wall we have: each team ships its own API, clients have to stitch together data from five or six endpoints, and every new feature means another round of coordination. GraphQL federation is an architecture that lets you compose multiple independently owned GraphQL services into a single, unified graph that clients query through one endpoint. In short, what is GraphQL federation? It is a way to give consumers one coherent API while your teams keep owning their slices of the domain separately. This post explains how it works, when it makes sense, and how it compares to a traditional API gateway.

What Is GraphQL Federation, Really?

GraphQL federation solves a specific organizational and technical problem: how do you expose a single graph without forcing all your services into one monolithic codebase?

In a federated setup, each service (called a subgraph) defines the portion of the schema it owns. A separate component (the router or gateway) composes those subgraphs into one supergraph and routes each part of an incoming query to the service responsible for it. The client sends one query. The router plans and executes it across the underlying services, then assembles the response.

The key insight is that entities can be extended across service boundaries. A User type might originate in an accounts service, but a reviews service can add a reviews field to that same User without the accounts team knowing or caring. Federation resolves the join at query time.

The most widely used implementation is Apollo Federation, an open specification with tooling from Apollo. Other implementations exist, including those compatible with the same directives, but Apollo Federation is the reference most teams start from.

The core building blocks

  • Subgraph: an individual GraphQL service that owns part of the schema.
  • Supergraph: the composed schema representing the entire graph.
  • Router / gateway: the runtime that receives client queries, builds a query plan, and executes it against subgraphs.
  • Entity: a type that can be referenced and resolved across multiple subgraphs, identified by a @key.

Why GraphQL for Microservices Is Hard Without Federation

When we first moved to GraphQL for microservices, the naive approach was schema stitching: manually merge schemas at a gateway layer. It worked, but it was brittle. Every change required updating stitching configuration, type conflicts were common, and the gateway became a bottleneck that no single team owned cleanly.

The deeper problem is ownership. Microservices exist because you want teams to deploy independently. A single hand-maintained GraphQL schema reintroduces the coupling you were trying to escape. You end up with:

  • A shared schema file that every team fights over.
  • A central team that becomes a deployment bottleneck.
  • Runtime coupling where one team's change breaks another team's queries.

Federation addresses this by making composition declarative and automated. Teams annotate their own schemas, and the composition process validates that everything fits together before anything reaches production.

How Federation Composes a Unified Graph

Let us make this concrete. Suppose you have two services.

The accounts subgraph owns the User entity:

type User @key(fields: "id") {
  id: ID!
  email: String!
  displayName: String!
}

type Query {
  currentUser: User
}

The @key directive marks User as an entity and declares that id uniquely identifies it. This is what allows other subgraphs to reference the same user.

The reviews subgraph extends User without owning it:

type User @key(fields: "id") {
  id: ID!
  reviews: [Review!]!
}

type Review @key(fields: "id") {
  id: ID!
  body: String!
  rating: Int!
  author: User!
}

Notice the reviews subgraph declares User again, but only adds the fields it is responsible for. To resolve those fields, it implements a reference resolver that takes the id and returns the entity representation:

const resolvers = {
  User: {
    __resolveReference(reference) {
      // reference = { __typename: "User", id: "123" }
      return { id: reference.id };
    },
    reviews(user) {
      return getReviewsByUserId(user.id);
    },
  },
};

Now a client can issue a single query:

query {
  currentUser {
    displayName
    reviews {
      rating
      body
    }
  }
}

The router builds a query plan: fetch currentUser from the accounts subgraph, take the returned id, then call the reviews subgraph's entity resolver to fetch reviews. The client never knows two services were involved.

Composition and schema checks

Before deployment, the individual subgraph schemas are composed into a supergraph. This step catches conflicts: mismatched field types, entities missing keys, or fields that reference types that no longer exist. In a mature pipeline, we run composition as a CI check so a subgraph change that would break the graph fails the build rather than production. This is one of the strongest arguments for federation over hand-stitching. The failure mode moves left, into code review and CI, instead of runtime.

API Gateway vs GraphQL Federation

A common question is api gateway vs graphql federation, and the honest answer is that they are not direct competitors. They solve overlapping but distinct problems.

A traditional API gateway typically handles:

  • Routing requests to backend services by path.
  • Authentication, rate limiting, and request transformation.
  • Aggregating REST endpoints, often with some manual response shaping.

GraphQL federation handles:

  • Composing a single typed schema from many services.
  • Planning and executing cross-service queries.
  • Resolving entity relationships that span service boundaries.

In practice, they coexist. You often place an API gateway in front of the federated router to handle cross-cutting concerns like edge authentication, TLS termination, and rate limiting, while the router owns graph composition and query planning.

The comparison table below summarizes the difference in intent:

Concern API Gateway GraphQL Federation
Primary unit HTTP endpoints Typed schema entities
Data joining Manual / custom Automatic via query plan
Client contract Per-endpoint Single unified graph
Team ownership Config-centric Schema-centric per subgraph

If your goal is to unify microservices API surfaces into one strongly typed contract that clients can introspect, federation is the mechanism. If your goal is edge policy enforcement, a gateway is the mechanism. Most serious platforms use both.

When Federation Is Worth It, and When It Is Not

Federation adds real operational surface area: a router to run and monitor, a composition pipeline to maintain, and a mental model your engineers need to learn. It pays off when:

  • You have multiple teams owning distinct domains and want independent deployment.
  • Clients currently make many round trips to assemble one view.
  • You need a single typed contract across a fragmented backend.

It is likely overkill when:

  • You have one or two services. A single GraphQL server is simpler.
  • Your clients are internal and tolerant of multiple calls.
  • Your team has no appetite for the added infrastructure.

We generally advise starting with a single GraphQL server and adopting federation only when team boundaries make a monolithic schema painful. Premature federation is a common and expensive mistake.

If you are weighing whether federation fits your platform, our platform and software engineering capabilities cover the architecture decisions and migration paths in more depth. We have also seen adoption patterns differ sharply by sector, which we discuss across the industries we work with.

Operational Realities to Plan For

Before you commit, budget for these:

  1. Observability across the graph. A slow query might touch four subgraphs. You need distributed tracing that follows the query plan, not just per-service logs.
  2. Schema governance. Naming conventions, deprecation policy, and ownership rules prevent the graph from becoming inconsistent.
  3. Performance and the N+1 problem. Entity resolution can generate many small requests. Use batching (such as DataLoader-style patterns) in reference resolvers.
  4. Versioning discipline. Federation encourages additive change and field deprecation over breaking changes. Enforce this in CI.
  5. Router placement. Decide where the router sits relative to your gateway, auth, and CDN layers.

None of these are dealbreakers. They are the cost of a unified graph, and they are far cheaper than the coordination tax of a hand-maintained shared schema.

FAQ

Is GraphQL federation the same as Apollo Federation?

No. GraphQL federation is the general architectural pattern. Apollo Federation is a specific, widely adopted specification and set of tools that implement it. You can use the federation pattern with Apollo's implementation or with other spec-compatible implementations.

Do all my services need to be GraphQL to use federation?

Each subgraph exposes a GraphQL schema, but the service behind it can call anything: REST APIs, databases, gRPC services, or legacy systems. A subgraph is a thin GraphQL layer over whatever data source it owns, so you can wrap existing services incrementally.

How is federation different from schema stitching?

Schema stitching merges schemas manually at a gateway, which becomes brittle as the number of services grows. Federation makes composition declarative through directives like @key, validates the combined schema in a composition step, and lets each team own its portion independently.

Does federation hurt performance compared to a single service?

It can, if you ignore the N+1 problem in entity resolution. Well-designed reference resolvers with batching keep overhead modest. The router adds a query-planning step, but for cross-service queries it typically replaces multiple client round trips with one, often improving perceived latency.

Can I adopt federation gradually?

Yes. A common path is to start with one GraphQL server, then split it into subgraphs as team boundaries emerge. You can migrate one domain at a time, keeping the client-facing graph stable throughout.