What are the _service and _entities fields in a federated subgraph, and what does each do?
answer
- _service.sdl = schema as text for composition
- _entities = reference resolver
- representation = __typename + key fields
- _Any scalar, _Entity union
- same-order return, null if unresolved
basics
~10 sEvery federated subgraph auto-exposes two special query fields. _service { sdl } returns the subgraph's schema as text so it can be composed. _entities(representations:[_Any!]!) takes references (like {__typename, id}) and returns the full objects.
solid answer
~40 sFederation adds two machine-facing fields to every subgraph's Query type. `_service` returns an `_Service` object whose `sdl` field is the subgraph's own schema in text form — the composition tool reads this to build the supergraph. `_entities(representations: [_Any!]!): [_Entity]!` is the reference resolver: the router passes an array of representations, each a map containing at least `__typename` plus the fields named in that type's `@key` (e.g. `{__typename: "Book", id: "42"}`), and the subgraph returns the fully resolved entities in the same order. `_Any` is a scalar for arbitrary JSON references; `_Entity` is a union of all `@key`-annotated types. In Spring for GraphQL you don't hand-write these — the federation support generates them, and your `@EntityMapping` controller methods supply the logic that `_entities` invokes per representation.
code
graphql · 14 lines# Auto-added to every subgraph's Query
type Query {
_service: _Service!
_entities(representations: [_Any!]!): [_Entity]!
}
scalar _Any
type _Service { sdl: String! }
union _Entity = Book | Author # every @key type
# Router calls it like:
# query { _entities(representations: [
# { __typename: "Book", id: "42" }
# ]) { ... on Book { title } } }go deeper
Know the two fields exist and roughly that one exposes the schema and one resolves references.
Explain representation shape (__typename + key), the _Any/_Entity/_Service types, and ordering contract.
Tie it to the query plan and explain how Spring maps representations to @EntityMapping automatically.
Discuss composition-time validation via _service.sdl and batching/order guarantees at scale.
## Why these fields exist Federation is a contract between a subgraph and the router. Two fields carry that contract, and both are prefixed with `_` to mark them as federation internals rather than business API. ## `_service { sdl: String! }` The root Query gains a field `_service: _Service!`, and `_Service` has one field `sdl: String!`. - **Purpose**: expose the subgraph's own schema (including federation directives like `@key`) as a string so tooling (Apollo `rover`, GraphOS, or the gateway on startup) can fetch and compose all subgraph SDLs into a supergraph. - **Composition** is when these SDLs are checked for compatibility (e.g. two subgraphs must agree on a shared entity's key) and merged. Composition failures are caught here, before runtime. ## `_entities(representations: [_Any!]!): [_Entity]!` This is the heart of cross-subgraph resolution, often called the **reference resolver**. - **`_Any`** is a custom scalar representing an opaque JSON object — an entity *reference*. - Each representation includes `__typename` (which entity type) plus that type's **key fields** (declared via `@key(fields: "...")`). Example: `{ "__typename": "Book", "id": "42" }`. - **`_Entity`** is an auto-generated union of every type in this subgraph that has a `@key`. - **Contract**: the subgraph must return a list of resolved entities **in the same order** as the input representations, with `null` for any it cannot resolve. ## The flow that uses them 1. Client sends `book(id:42){ title reviews{ stars } }` to the router. 2. Router's query plan: get `Book` + `title` from the catalog subgraph, then get `reviews` from the reviews subgraph. 3. To do step 2 it calls the reviews subgraph's `_entities` with `[{__typename:"Book", id:"42"}]`, gets the `Book` stub back, then resolves `reviews` on it. ## Spring for GraphQL specifics You never write `_service` or `_entities` by hand. When federation support is enabled (via `FederationSchemaFactory`), Spring: - adds these fields and the `_Any`/`_Entity`/`_Service` types, - routes each incoming representation to the matching `@EntityMapping` method by `__typename`, - binds the representation's key fields to `@Argument`-annotated parameters (or hands you the whole `Map<String,Object>`), - and preserves ordering for you. ## Gotchas - **Ordering matters**: the returned list must align positionally with `representations`. Spring handles this when you use one `@EntityMapping` per type, but if you resolve in batch you must preserve order yourself. - **`__typename` is required** in every representation; without it the subgraph cannot dispatch. - These fields being present is how a tool detects the service is a federated (v2) subgraph, alongside the `@link` to the federation spec.
- What must each representation passed to _entities contain?At minimum `__typename` to select the entity type, plus every field listed in that type's `@key` directive so the subgraph can look the entity up.
- Who calls _entities in practice?The Apollo Router/gateway during query execution, not the client. It's federation internal plumbing; clients query normal business fields.