Decision record

AD-0002 Cosmo as the federation platform

Status: accepted. Date: 2026-08-27.

Context

AD-0001 chose federation, and the README is plain that federation is a platform problem rather than a library problem. Composition, breaking-change checks, a registry that knows what is deployed and a planner in front all have to come from somewhere, and a plain GraphQL server supplies none of them. The README also fixes who the platform has to suit, organisations with fewer than twenty-five engineers, and among them the defence, rail, energy and medical device work that has to run air-gapped.

Cosmo’s licence is the first fact. The wundergraph/cosmo monorepo carries one licence file, the standard Apache License 2.0 text, with no per-directory licence and no enterprise, commercial or source-available exception, and the router module, wgc 0.130.1 and @wundergraph/composition 0.63.3 all declare Apache-2.0 in their package metadata. The vendor states the platform runs without licence fees or feature gates, and “will always remain so” is a promise rather than a licence term, so the versions are pinned. The README describes the main alternative as being under a licence the OSI does not recognise as open source, and the vendor comparison the research quotes names it as Apollo’s router under ELv2.

The second fact is that the router runs without a control plane. wgc router compose composes locally and “does not interact with the control plane”, the router loads the output from EXECUTION_CONFIG_FILE_PATH, and Start() takes the static-config branch before any poller is consulted. No graph token is required with a static config, and with the token empty the default Cosmo Cloud exporters are disabled. Two vendor caveats sit beside that. The compose page says “it is recommended to not use this for production” and the router logs “Not recommended for Production” at every start without a token. Since router 0.215.0 an anonymous usage tracker has been on by default, gated on neither the token nor the static config and switched off only by DO_NOT_TRACK=1 or COSMO_TELEMETRY_DISABLED=true. The README’s “no network dependency at all” is true only with those set, so the public wording carries both caveats rather than going around them.

Two more facts shape how the platform is used rather than whether. The Go composition library was removed from Cosmo on 2026-05-06, so composition needs Node and happens outside the build with its output committed. The router’s Go module has only commit pseudo-versions and has broken its API twice, so the router is a copied binary driven by configuration rather than a library. The README’s deeper reason for Cosmo is that its subgraphs can now be compiled to protobuf and served over gRPC with GraphQL kept as the schema language, which the README reads as an admission that the valuable part was never the wire format.

Decision

We will use WunderGraph Cosmo as the federation platform, pinned to router 0.343.1 and wgc 0.130.1 and bumped together, run from a static execution configuration with no control plane, no graph token and telemetry switched off by DO_NOT_TRACK=1, COSMO_TELEMETRY_DISABLED=true, TRACING_ENABLED=false and METRICS_OTLP_ENABLED=false baked into the image. The router binary is copied out of the vendor’s image with its Apache-2.0 licence text beside it and started as a child process, composition is a maintainer step whose output is committed and guarded by a Go test that compares each embedded schema with the schema file it came from, and all three subgraphs stay standard GraphQL subgraphs so that subscriptions work.

Alternatives considered

A plain GraphQL server with one schema. The README’s answer is that it is not federation at all, and AD-0001 records why a single service lost.

Apollo’s router, the main alternative platform. The README does not name it and rejects it on licence alone, one the OSI does not recognise as open source, which for an argument aimed at small organisations is not a footnote. The research has only the vendor’s comparison for the ELv2 label and examined Apollo no further.

Cosmo’s gRPC services and its extension-module subgraph route, which the research listed as its fourth and fifth options. Both keep the GraphQL SDL as the contract and are the direction the README admires, and both explicitly do not support subscriptions, so the two-app live update would fall back to polling. The research keeps the extension-module route for a later second example.

Consequences

The demo can be launched with nothing but Docker and run with the network removed, once the four variables are set. Composition runs on any machine with Node and no account anywhere, the router starts from a file, and the playground is where a visitor sees three services answer one query (SR-43). Everything checked is Apache-2.0, and the pinned versions stay so.

The public text has to carry the vendor’s position. Wherever it describes static composition it quotes “it is recommended to not use this for production” and says what the demo does about it, which is that no control plane exists to fetch from and the configuration is committed and tested for drift, and the README’s air-gap sentence gains the qualification and names the image’s variables. CI has no Node, so the committed configuration is all it can check, and SR-42’s drift test is the third condition’s whole evidence. Router and wgc are pinned together because the router refuses to start on an execution config whose compatibility version exceeds its threshold, and every router bump is a rebuild of the demo image. The router binary is about 40 MB compressed and sets the floor of SR-06’s budget. The licence text travels with the binary (SR-07) and the repository carries a NOTICE (SR-08).

Four spikes belong to this decision. The first runs the image under docker run --network none at debug log level and watches for connection attempts before the air-gap claim goes public, which is SR-03’s demonstration. The second composes the three draft schemas with wgc and runs gqlgen over the nested @requires, which the research never ran. The third starts the copied binary from the supervisor with environment alone in a distroless image with no YAML file present. The fourth observes what /health/ready reports with the subgraph ports closed.

Requirements affected

SR-03, SR-07, SR-42, SR-43

Sources

The repository README, “Why Cosmo, and not simply GraphQL”. The LICENSE file at the root of wundergraph/cosmo and the package metadata of router 0.343.1, wgc 0.130.1 and @wundergraph/composition 0.63.3. The vendor’s pages on wgc router compose and on running the router from a static execution configuration, and router/.env.example for the telemetry variables. The commit that removed composition-go. What the research overturned gives the readings this record rests on and marks the ones that stayed unverified.