Part 6: GraphQL Federation — TypeScript Gateway and Python Subgraph

Splitting a Monolith Without a Big Bang

When I first built a GraphQL API to serve a React frontend and a mobile app, everything was in a single Apollo Server. One schema, one deployment, one team owning everything. It worked fine until a second team needed their own domain added to the graph — then the monolith started to become a coordination problem.

Apollo Federation solves this by letting each service own its slice of the graph. Services are subgraphs and are unified behind a supergraph gateway (Apollo Router). The client still sends queries to one endpoint. The gateway decomposes those queries, fans them out to the right subgraphs, and assembles the final response.

The architecture we build in this part:

┌─────────────────────────────────────────────────────────┐
│  Apollo Router (supergraph gateway — localhost:4000)    │
└────────────────┬────────────────────────────────────────┘

     ┌───────────┴────────────┐
     │                        │
┌────▼────────────────┐  ┌────▼──────────────────────┐
│  TypeScript         │  │  Python (Strawberry)       │
│  Product Subgraph   │  │  Inventory Subgraph        │
│  localhost:4001     │  │  localhost:4002             │
│  @apollo/subgraph   │  │  strawberry.federation     │
└─────────────────────┘  └────────────────────────────┘

The client queries Apollo Router. The router internally routes:

  • product, products, createProduct → TypeScript Product Subgraph

  • stockLevels, replenishmentSchedule → Python Inventory Subgraph

Both subgraphs know about the Product entity, and federation allows the Python service to extend the TypeScript service's Product type with additional fields.

Apollo Federation v2 Key Concepts

Before the code, a glossary:

Term
Meaning

Subgraph

An individual GraphQL service that contributes types and fields to the supergraph

Supergraph

The combined schema produced by composing all subgraphs

Entity

A type with an @key directive — it can be referenced and extended across subgraphs

@key

Marks a field (or set of fields) as the unique identifier for an entity

@external

Marks a field that is defined in another subgraph but referenced here

@requires

Declares that a resolver needs fields from the owning subgraph before it can run

@provides

Declares that a resolver will supply fields normally fetched from another subgraph

Reference resolver

A special __resolveReference function that reconstructs an entity from its @key fields

Apollo Router

The Rust-based high-performance gateway that routes queries across subgraphs

Step 1 — TypeScript Product Subgraph

Convert the Apollo Server from Part 3 into a federation subgraph.

Add federation directives to the SDL:

Add reference resolvers (called by the gateway when it needs to reconstruct a Product entity):

Replace ApolloServer with a federation-aware build:

Step 2 — Python Inventory Subgraph with Strawberry

The Python service owns inventory data (warehouse stock levels, replenishment schedules). It knows about Product entities from the TypeScript service and extends them with inventory fields.

Strawberry Schema with Federation

FastAPI Entry Point

Step 3 — Apollo Router

Apollo Router is a Rust binary that acts as the supergraph gateway. It reads a supergraph schema composed from all subgraph SDLs.

Install Rover CLI and Apollo Router

Compose the Supergraph Schema

Router Config

Start the Router

Step 4 — Cross-Service Query in Action

With both subgraphs and the router running, this query works:

The router's query plan:

  1. Route product(id: $id) { id name price } → TypeScript Product Subgraph

  2. Receive the product's id from step 1

  3. Route { _entities(representations: [{__typename: "Product", id: "..."}]) { ... on Product { stockLevels { ... } replenishmentSchedule { ... } } } } → Python Inventory Subgraph

  4. Merge both responses and return a single result to the client

The client is completely unaware that two services were involved.

Docker Compose for Local Development

What's Next

You now have a working federated GraphQL supergraph:

  • TypeScript Apollo Server as a subgraph — owns Product and Category

  • Python Strawberry as a subgraph — owns StockLevel and extends Product

  • Apollo Router composing both into a single endpoint

In Part 7, we test both subgraphs in isolation, measure and fix query performance, and set up a production deployment.

Last updated