Launch GraphOS Studio

Enforcing entity ownership in Apollo Federation

Designating entity ownership in Apollo Federation 2


In Federation 2, the notion of "extending" an type is strictly conceptual. All definitions of a type in different are merged according to the "shareability" of . In the following example, neither subgraph really owns or extends the Product . Instead, they both contribute to it.

type Product @key(fields: "id") {
id: ID!
name: String
type Product @key(fields: "id") {
id: ID!
reviews: [Review]

Federation 1 required that one of these definitions used the extend keyword or @extends . Federation 2 drops this requirement to improve the flexibility of and reduce the possibility of hard composition errors.

However, in some situations you still might want to designate an "owner" of an and make "entity extension" a first-class concept in your .

One example is the ability assert which is responsible for an . If two subgraphs add different descriptions to a type, selects one of those descriptions and emits a hint informing you of the inconsistency:

HINT: [INCONSISTENT_DESCRIPTION]: Element "Product" has inconsistent
descriptions across subgraphs. The supergraph will use description
(from subgraph "one"):
The Product type lorem ipsum dolar sit amet.
In subgraph "two", the description is:
This is my description of the Product type.


When a description is inconsistent across , selects the description from the first subgraph alphabetically by name.

A mechanism for deciding the "owner" of the type allows tools such as linters to catch these inconsistencies early in the development process.

Creating an @owner directive

You can add an @owner to your using the @composeDirective functionality introduced in Federation 2.2.

extend schema
@link(url: "", import: ["@key", "@composeDirective"])
@link(url: "")
@composeDirective(name: "@owner")
directive @owner(team: String!) on OBJECT
type Product @key(fields: "id") @owner(team: "subgraph-a") {
id: ID!
name: String

The @owner now appears in the . Because we did not define the directive as repeatable, cannot define it with different .

Writing a lint rule using the @owner directive

Here's an example of a @graphql-eslint rule for that uses the @owner to determine if a description is required:

Using @owner to determine required approvers

Another use case for the @owner is to determine required reviewers when a schema change affects a type owned by another team.

The exact process depends on your source control and continuous integration systems. The following example steps assume you're using GitHub for both.

  1. Add a pull_request workflow:

    name: Add required reviewers for owned GraphQL types
    on: [pull_request]
  2. Determine the affected types in the schema change:

    import { diff } from "@graphql-inspector/core";
    import { buildSchema } from "graphql";
    const differences = diff(
    buildSchema(schemaFromBaseRef, { assumeValidSDL: false }),
    buildSchema(schemaFromCurrentRef, { assumeValidSDL: false })
    /* Derive a list of affected types from the result:
    "criticality": {
    "level": "NON_BREAKING"
    "type": "FIELD_ADDED",
    "message": "Field 'newField' was added to object type 'Product'",
    "path": "Product.newField"
  3. Obtain the .

    You can use rover supergraph fetch or retrieve it using the Apollo Platform API.

  4. Extract the owners for the affected types:

    import { getDirective } from "@graphql-tools/utils";
    const supergraphSchema = buildSchema(supergraphSdl);
    const affectedTeams = [];
    for (const typeName of affectedTypes) {
    const type = supergraphSchema.getType(typeName);
    const owner = getDirective(schema, type, "owner")?.[0];
    if (owner) {
  5. Add the team as reviewers on the pull request:

    import { Octokit } from "@octokit/action";
    const octokit = new Octokit();
    const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
    await octokit.pulls.requestReviewers({
    pull_number: pullNumber, // ${{ github.event.number }}
    team_reviewers: affectedTeams,
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy