skip to content

What are the _service and _entities fields in a federated subgraph, and what does each do?

level: middleimportance: must knowfreq 55%

answer

  1. _service.sdl = schema as text for composition
  2. _entities = reference resolver
  3. representation = __typename + key fields
  4. _Any scalar, _Entity union
  5. same-order return, null if unresolved

basics

~10 s

Every 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 s

Federation 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
graphql
# 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

for a junior

Know the two fields exist and roughly that one exposes the schema and one resolves references.

for a middle

Explain representation shape (__typename + key), the _Any/_Entity/_Service types, and ordering contract.

for a senior

Tie it to the query plan and explain how Spring maps representations to @EntityMapping automatically.

for a principal

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.

context