GraphQL

Federation And Distributed Graphs

The Problem: One Graph, Many Teams

Clients genuinely benefit from one unified graph — one endpoint, one type system, queries that join anything to anything. But a single implementation of that graph means every team's resolvers, deploys, and outages share one service. The naive alternative — separate GraphQL APIs per team — pushes the joining problem onto every client ("call the catalog API, then the reviews API, then stitch"). Federation keeps the one graph client experience while distributing the implementation along team boundaries.

The Architecture: Subgraphs, Router, Supergraph

A federated system has three parts:

  • Subgraphs — ordinary GraphQL services, each owning a slice of the schema. A Catalog service owns Artist and Album; a Reviews service owns Review; an Accounts service owns User.
  • A composed supergraph schema — produced at build time by a composition step that merges the subgraph schemas, checks them for conflicts, and records which subgraph answers which field.
  • The router (or gateway) — the one endpoint clients see. It holds the supergraph schema, and for each incoming operation builds a query plan: split the selection set by owning subgraph, call them in the right order, and reassemble one response.

Clients notice nothing. A query touching artists and reviews just works; the router fans out behind the scenes.

Entities: Types That Span Services

The interesting mechanics are types that multiple subgraphs contribute to. Reviews wants to add a reviews field to Album, but Catalog owns Album. Federation solves this with entities: a type declared with a key (typically id) that other subgraphs can extend.

Conceptually, in the Reviews subgraph's SDL:

type Album @key(fields: "id") {
  id: ID!
  reviews(first: Int = 10): [Review!]!
  averageRating: Float
}

Reviews is saying: "given an album's id, I can supply these fields." When a query asks for an album's title (Catalog) and reviews (Reviews), the router fetches the album from Catalog, then passes its key to Reviews' entity resolver — a special lookup each subgraph implements meaning "here is a key, hydrate my fields for it" — and merges the two halves.

The design consequence: field ownership follows data ownership. The team whose service stores review data serves review fields, even on types "belonging" to another team. Composition enforces that exactly one subgraph resolves each field, so ownership is structural rather than a wiki page — a mechanical version of the previous lesson's governance.

What Changes Operationally

Federation moves complexity; it does not remove it:

  • Composition failures become your build breaks. Two subgraphs claiming the same field, or an entity key mismatch, fails composition — this is good (broken graphs never deploy) but adds a cross-team CI pipeline that must run on every subgraph release.
  • Query planning adds latency and new N+1s. A deep query may become sequential subgraph calls; entity resolvers get lists of keys and must batch-load them (the loader discipline from the performance lesson, now across services).
  • Observability must be end to end. A slow query is now a distributed trace across router and subgraphs; per-subgraph timing in the router is table stakes.
  • Security concentrates at the router. Authentication, cost limits, and persisted-query allowlists run once at the edge; subgraphs verify router-forwarded identity (and should not be directly reachable from the internet). Authorization stays in each subgraph's business layer, right where the earlier lesson put it.

Alternatives And When To Say No

Two related approaches predate or complement federation. Schema stitching merges schemas at the gateway in code — more manual wiring, more flexibility, no per-subgraph spec support required. A plain BFF (backend-for-frontend) GraphQL server that calls internal REST/gRPC services is not distributed at all — one team owns the graph and does the joining — and is the right answer far more often than its unglamorousness suggests.

Choose federation when several teams each need to ship schema independently and the org is committed to router infrastructure, composition CI, and distributed tracing. One team with one deployable does not need it, whatever the microservice diagram says; a single well-governed graph (or a BFF) is simpler, faster, and easier to secure. Federation is an organizational scaling tool — adopt it when the organization, not the traffic, demands it.

What To Check

Before moving on, make sure you can:

  • explain the client-visible promise of federation and why per-team separate APIs break it
  • name the three architecture parts and what happens at composition time versus request time
  • describe entities: keys, cross-subgraph field contribution, and entity resolvers
  • state where authentication, cost control, and authorization each live in a federated system
  • position stitching and the BFF pattern against federation, and argue when each wins

What You Should Be Able To Do

After this lesson — and this track — you should be able to reason about GraphQL at every scale: a single PHP endpoint, a governed multi-team schema, or a federated graph. For federation specifically, you should be able to sketch subgraph boundaries along data ownership for a domain like the music catalog, predict the query plan for a cross-service query, and make the honest call about whether your organization needs federation at all.