Federation

GraphWeaver generates a client for the whole graph, so with Apollo Federation you point it at the composed schema — the supergraph or the API schema — not at individual subgraph files.

The schema you feed it

Three artifacts, easy to mix up:

Artifact What it is Feed to weaver?
Subgraph SDL one service's .graphql, with @key/@shareable/extend schema @link No — it's a fragment of the graph, and its federation directives are declared elsewhere (imported via @link), so plain SDL loading rejects them
Supergraph the composed graph, annotated with @join__*/@link machinery Yes — self-contained (see below)
API schema the supergraph with federation internals stripped — exactly what the router serves and what an introspection query returns Yes — the exact client contract

SchemaLoader.load (and Client.new(path_or_sdl)) take the supergraph or the API schema as an SDL file or introspection dump; or point weaver at the router URL to introspect the API schema live.

Pointing weaver at a supergraph

A supergraph SDL works as-is. When SchemaLoader sees the @join__* markers it strips the composition machinery before building the schema — the synthetic join__*/link__* types and directive definitions, and every @join__*/@link application on the real types — so what codegen sees is the merged graph's ordinary type shapes, with no federation plumbing leaking into schema.types. (It's a pure AST rewrite of the SDL; no graphql-ruby monkeypatch, and plain schemas pass through untouched.) Field shapes — nullability, args, enums, inputs — are identical to the API schema, so your generated structs are correct; and because codegen is query-driven, nothing federation-internal could generate code anyway.

A supergraph is a superset of the API schema — it carries elements the public API hides, marked @inaccessible. Weaver removes those on load (below), so the schema it generates against is the API schema, not the superset.

@inaccessible

A federation-v2 directive marking an element as present in the federated graph but removed from the public API schema. Its common use is safely rolling out a change to a shared type: add the field to one subgraph marked @inaccessible (so composition doesn't require every subgraph to have it yet), roll it out to the rest, then drop the directive to publish it. (Apollo contracts also pair @tag + @inaccessible to build filtered API variants.) It's a fed-v2 feature — common in mature, multi-team graphs with lots of shared types, rare in small or young ones, and targeted where present (a handful of elements, not every field).

Weaver derives the API schema from the supergraph for you: loading strips every @inaccessible element and cascades — a field/argument/union-member/interface referencing a removed type goes too, and a type left empty is removed in turn — so codegen validates against exactly what clients can query. There's no over-permit gap, and no need for Apollo's JS tooling (@apollo/federation-internals) to subtract the API schema first; feed weaver the raw supergraph and you get the router's contract. (This is a pure SDL rewrite at load time — see SchemaLoader.)

Other federation directives hide nothing from the schema, so weaver keeps the field and ignores the directive: @requiresScopes / @policy / @authenticated enforce access at runtime; @tag / @requires / @provides / @external are metadata.

Which schema to feed

Any of these — they all produce the same generated code:

  • The supergraph SDL — weaver strips the @join__*/@link machinery and derives the API schema (removing @inaccessible). The common case.
  • The API schema SDL — already subtracted (e.g. emitted in your CI); loads as an ordinary schema.
  • The live router — introspect it; it already serves the API schema.

A large real supergraph carries more constructs than a toy one (interface objects via @join__type(isInterfaceObject:), @join__unionMember, enum join directives). The stripping holds across them, but the honest check is to run codegen against your actual composed schema plus a couple of representative queries before relying on it.