Technology Apr 25, 2026 · 6 min read

What Actually Happens When a Query Hits Your WunderGraph Cosmo Supergraph

A plain-English breakdown for developers migrating from Apollo GraphOS — or just trying to understand Federation for the first time. If you’ve read the WunderGraph Cosmo documentation and still aren’t sure exactly what’s happening when a client query arrives at your supergraph, this is the post...

DE
DEV Community
by Jordan Sterchele
What Actually Happens When a Query Hits Your WunderGraph Cosmo Supergraph

A plain-English breakdown for developers migrating from Apollo GraphOS — or just trying to understand Federation for the first time.

If you’ve read the WunderGraph Cosmo documentation and still aren’t sure exactly what’s happening when a client query arrives at your supergraph, this is the post you needed first.

Federation documentation tends to explain the what — subgraphs, the router, the schema registry — but not the why or the how in plain English. This post fills that gap. By the end, you’ll understand what Cosmo is actually doing on every request, why it’s architecturally different from a monolithic GraphQL API, and what you gain by switching from Apollo GraphOS.

The Problem Federation Solves

A monolithic GraphQL API has one schema, one server, one team responsible for all of it. This works until it doesn’t. When the schema grows to thousands of fields, when three teams need to modify it simultaneously, when one service’s latency drags down the entire response — you start feeling the ceiling.

Federation answers: what if each team owned their own schema, their own service, and contributed to a single unified API?

That’s the supergraph. One API surface for your clients. Distributed ownership underneath.

The Five Components of a Cosmo Setup

Before tracing a query, you need to know what the pieces are:

1. Subgraphs
Individual GraphQL services owned by specific teams. Each has its own schema, its own server, its own deployment. The Products team owns the Products subgraph. The Orders team owns the Orders subgraph. They don’t need to coordinate schema changes — they just need to follow Federation’s composition rules.

2. The Router
The single entry point to your supergraph. When a client query arrives, it goes to the Router. The Router decides which subgraphs to call, in what order, and how to merge the results. It’s stateless, high-performance (written in Go), and deployable anywhere.

3. The Schema Registry
Cosmo’s control plane. Every time a subgraph schema changes, the updated schema is pushed to the Registry. The Registry composes all subgraph schemas into the unified supergraph schema and runs composition checks to catch breaking changes before they reach production.

4. The Control Plane (cosmo.wundergraph.com or self-hosted)
Manages configuration, analytics, tracing, and schema history. The Router polls this for its configuration — which subgraphs exist, how to route queries, what the current supergraph schema looks like.

5. The Client
Your frontend, mobile app, or any API consumer. It sends a single GraphQL query to the Router’s endpoint. It has no idea how many subgraphs exist underneath.

What Actually Happens on a Query — Step by Step

Let’s say a client sends this query:

query GetOrderWithProducts {
  order(id: "ord_123") {
    id
    createdAt
    products {
      name
      price
      inventory
    }
  }
}

order is owned by the Orders subgraph. products on an order is owned by the Products subgraph.

Here’s what Cosmo’s Router does:

Step 1 — Query Planning
The Router receives the query and runs it through the query planner. The query planner looks at the supergraph schema — which it loaded from the control plane at startup — and builds an execution plan. It knows that order comes from the Orders subgraph and that products under an order requires a call to the Products subgraph with a specific entity key.

The query planner uses a breadth-first execution strategy with Dataloader 3.0, which means it batches subgraph calls intelligently rather than making sequential round trips. This is one of the key performance advantages over Apollo Gateway.

Step 2 — Subgraph fetch: Orders
The Router sends a subquery to the Orders subgraph:

query {
  order(id: "ord_123") {
    id
    createdAt
    _productIds  # the entity key the Router needs to fetch from Products
  }
}

The Orders subgraph responds with the order data plus the product IDs needed to resolve the products field.

Step 3 — Entity resolution: Products
The Router sends a representation query to the Products subgraph:

query {
  _entities(representations: [
    { __typename: "Product", id: "prod_001" },
    { __typename: "Product", id: "prod_002" }
  ]) {
    ... on Product {
      name
      price
      inventory
    }
  }
}

The Products subgraph resolves each product by its entity key and returns the requested fields.

Step 4 — Result merging
The Router takes the responses from both subgraphs and merges them into the shape the client originally requested:

{
  "data": {
    "order": {
      "id": "ord_123",
      "createdAt": "2026-04-23T14:30:00Z",
      "products": [
        { "name": "Widget Pro", "price": 4900, "inventory": 142 },
        { "name": "Widget Lite", "price": 2900, "inventory": 58 }
      ]
    }
  }
}

The client receives exactly what it asked for. It never knew two subgraphs were involved.

What’s Different About Cosmo vs. Apollo GraphOS

If you’re migrating from Apollo, here’s what actually changes:

The Router is open-source and self-hostable. Apollo Router Pro is source-available with licensing restrictions. Cosmo’s Router is Apache 2.0. You can inspect every line, contribute fixes, and deploy it on your own infrastructure without a usage-based contract.

No vendor lock-in on the control plane. Apollo GraphOS requires their cloud. Cosmo offers a managed service at cosmo.wundergraph.com or full self-hosting via Docker Compose and Helm charts. On The Beach, one of Cosmo’s enterprise customers, reported 30% infrastructure cost reduction by self-hosting the Router.

Migration is one command. If you have an existing Apollo Studio setup, the migration path is: copy your Apollo API key, paste it into the “Migrate from Apollo” option in cosmo.wundergraph.com, run the generated docker run command. Your subgraphs don’t change. Only the control plane does.

Performance. Cosmo’s query planner is written in Go with AST-JSON based result merging. Users have reported better P99 latency and higher requests-per-second compared to Apollo Router on the same workloads.

The Production Configuration Layer People Miss

This is where new Cosmo users stall.

Getting Federation working locally is straightforward. Getting it production-ready requires understanding a second layer of configuration that the getting-started docs don’t cover:

Introspection. Enabled by default. Should be disabled in production — it exposes your full schema to anyone who queries it. Add introspection: false to your router config.

Development mode. Enables Advanced Request Tracing (ART) for debugging. Contains sensitive information. Should never be on in production. Add dev_mode: false.

Rate limiting. Cosmo’s Router supports Redis-backed rate limiting with per-key overrides. Useful when you have LLM-based clients generating high query volumes alongside regular API consumers. Requires a Redis instance.

Log level. Default is INFO. In production, set to ERROR. The difference in log volume matters at scale.

The Cosmo Hardening Guide covers all of this. Read it before your first production deployment.

Try It in Five Minutes

# Clone the repo
git clone https://github.com/wundergraph/cosmo.git
cd cosmo

# Run the full stack locally (Docker required)
docker-compose up

# Your supergraph is now running at localhost:3002
# The Studio is at localhost:3000

The repo includes example subgraphs you can modify to see composition, schema checks, and routing in action before writing a line of your own code.

What to Read Next

Built by AXIOM — an agentic developer advocacy workflow powered by Anthropic’s Claude, operated by Jordan Sterchele. Human-reviewed before publication.

DE
Source

This article was originally published by DEV Community and written by Jordan Sterchele.

Read original article on DEV Community
Back to Discover

Reading List