Docs
Launch GraphOS Studio

Changes from Federation 1 to Federation 2


Apollo Federation 2 provides developer experience improvements to the original specification for (called Federation 1 in these docs). If your organization has an existing Federation 1 , this article summarizes the benefits of moving to Federation 2.

If you're just getting started with Federation, check out the Quickstart.

What isn't changing?

Before covering what's new, here's what isn't changing in Federation 2:

  • Most importantly, Federation 2 is backward compatible with most Federation 1 supergraphs. You can probably move your existing to use Federation 2 without making any changes.

    • s that do require changes are s that should cause errors, but Federation 1 fails to detect them. Learn more.
    • To take full advantage of Federation 2 features, you do need to make some changes to your s, but you can make these changes incrementally at your convenience. See Moving to Apollo Federation 2.
  • s have no additional requirements. Any subgraph-compatible library is automatically compatible with Federation 2.

    • Many -compatible libraries do not yet automatically define certain s that are new in Federation 2, such as @shareable. You can define these directives manually to use them in your s.

More flexible composition

Federation 2 improves the flexibility and independence of your subgraph schemas. New logic is more flexible compared to Federation 1, meaning teams can more confidently build out their s or migrate functionality between subgraphs.

Let's look at some examples!

Value types

In Federation 1, multiple s can define the same type, but those definitions must all be identical. These identical shared types are called value types:

Fed. 1

Subgraph A
type Book {
title: String!
author: String!
}
Subgraph B
type Book {
title: String!
author: String!
}

In Federation 2, this "identical definition" constraint is removed. Value types and their s can be shared across s, even if certain details differ between definitions.

For details, see the sections below, along with Value types.

Objects

In Federation 2, an can be shared between s like so:

Fed. 2

Subgraph A
type Book @shareable {
title: String!
author: String!
}
Subgraph B
type Book @shareable {
title: String!
author: String # Nullable
isbn: String! # Not in A
}

The two Book type definitions above differ in terms of the s they include and the nullability of those fields. Notice also the new @shareable , which is required to indicate that a can be resolved by multiple s.

Marking a type as @shareable (as with Book above) is equivalent to marking all of its s as @shareable.

This flexibility is especially helpful when an organization has multiple standalone APIs that they want to unify with federation. Such APIs often share some types, and this added flexibility reduces the work required to compose their schemas successfully.

Valid shared field differences between subgraphs

  • The return type of a shared can vary in nullability (String / String!).
  • Types can omit s that are included in other s, as long as every in your is always resolvable. (For details, see Rules of composition.)

For details on how these differences are handled, see Differing shared fields.

Enums, unions, and interfaces

In Federation 2, enum, union, and interface definitions can differ between s. For details, see Merging types from multiple subgraphs.

Entities

Federation 2 introduces subtle but powerful changes to entities.

Originating subgraphs

In Federation 1, an entity originates in one and is then extended in other s:

Fed. 1

Products (originating)
type Product @key(fields: "id") {
id: ID!
name: String!
price: Int
}
Inventory (extending)
extend type Product @key(fields: "id") {
id: ID! @external
inStock: Boolean!
}

In Federation 2, entities do not have an "originating ." Instead, each subgraph can define an entity and contribute s to it:

Fed. 2

Products
type Product @key(fields: "id") {
id: ID!
name: String!
price: Int
}
Inventory
type Product @key(fields: "id") {
id: ID!
inStock: Boolean!
}

For details, see Contributing entity fields.

Shared entity fields

In Federation 1, each entity is resolved by exactly one (unless it's a @key or part of a @provides ). In Federation 2, multiple s can resolve the same entity if they all mark it with the @shareable :

Fed. 2

Products
type Product @key(fields: "id") {
id: ID!
name: String! @shareable
price: Int
}
Inventory
type Product @key(fields: "id") {
id: ID!
name: String! @shareable
inStock: Boolean!
}

For more information, see Resolving another subgraph's field.

Changes to @key

Federation 2 adds a new optional to the @key : resolvable. You can set this to false to indicate that a particular doesn't define a reference resolver for that entity.

For example:

Fed. 2

Products
type Product @key(fields: "id") {
id: ID!
name: String!
price: Int
}
Reviews
type Product @key(fields: "id", resolvable: false) {
id: ID!
}
type Review {
product: Product!
score: Int!
}

In this case, the Reviews references the Product entity by using it as the return type for Review.product. However, the doesn't contribute any unique s to Product, so it doesn't need to define a reference for it. Therefore, the "stub" definition of Product in the Reviews can include resolvable: false.

For more information, see Referencing an entity without contributing fields.

Migrating fields

Federation 2 introduces the @override directive, which helps you safely migrate entity and root-level s between s with :

Payments subgraph
type Bill @key(fields: "id") {
id: ID!
amount: Int!
}
type Payment {
# ...
}
Billing subgraph
type Bill @key(fields: "id") {
id: ID!
amount: Int! @override(from: "Payments")
}

For details, see Entity migration.

Interfaces implementing interfaces

Federation 1 incorrectly fails if an interface type implements another interface. This issue is resolved in Federation 2:

Fed. 2

interface Media {
title: String!
}
interface Book implements Media {
title: String!
author: String!
}
Previous
Subgraph specification
Next
Steps to move
Edit on GitHubEditForumsDiscord