Join us from October 8-10 in New York City to learn the latest tips, trends, and news about GraphQL Federation and API platform engineering.Join us for GraphQL Summit 2024 in NYC
Docs
Start for Free

Changes from Apollo Federation 1

Learn what's new in Apollo Federation 2


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

💡 TIP

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 . You can probably move your existing supergraph to use Federation 2 without making any changes.

    • that do require changes are graphs that should cause composition 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 , but you can make these changes incrementally at your convenience. See Moving to Apollo Federation 2.
  • have no additional requirements. Any subgraph-compatible library is automatically compatible with Federation 2.

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

More flexible composition

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

Let's look at some examples!

Value types

In Federation 1, multiple 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 can be shared across subgraphs, 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 subgraphs 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 fields 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 subgraphs.

NOTE

Marking a type as @shareable (as with Book above) is equivalent to marking all of its fields 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 field can vary in nullability (String / String!).
  • Types can omit fields that are included in other subgraphs, as long as every field in your is always resolvable. (For details, see Rules of composition.)

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

Enums, unions, and interfaces

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

Entities

Federation 2 introduces subtle but powerful changes to entities.

Originating subgraphs

In Federation 1, an originates in one subgraph and is then extended in other subgraphs:

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 don't have an "originating subgraph." Instead, each subgraph can define an entity and contribute fields 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 field is resolved by exactly one subgraph (unless it's a @key field or part of a @provides directive). In Federation 2, multiple subgraphs can resolve the same entity field if they all mark it with the @shareable directive:

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 directive: resolvable. You can set this argument to false to indicate that a particular subgraph 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 subgraph references the Product entity by using it as the return type for Review.product. However, the subgraph doesn't contribute any unique fields to Product, so it doesn't need to define a reference for it. Therefore, the "stub" definition of Product in the Reviews subgraph 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 fields between subgraphs 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 composition 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
Rate articleRateEdit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc., d/b/a Apollo GraphQL.

Privacy Policy

Company