Backward Compatibility in Apollo Federation 2
Navigating the transition from Apollo Federation 1 to Federation 2
Is official support ending for @apollo/gateway
v0.x?
Yes. As of 15 November 2022, @apollo/gateway
v0.x is officially deprecated, with end-of-life scheduled for 22 September 2023. @apollo/gateway
v2.x remains fully supported.
Learn more about deprecation and end-of-life.
Do I need to modify my subgraph schemas to use Federation 2?
Eventually. The process of moving to Federation 2 has three steps:
Upgrade your gateway to support Federation 2 (we recommend moving to the GraphOS Router).
Begin composing your supergraph schema with Federation 2 composition logic.
Update your individual subgraphs to use Federation 2 features and directives.
Steps 1 and 2 usually require no changes to your subgraph schemas. Schemas that do require changes are schemas that should cause certain composition errors that Federation 1 fails to detect (see below.).
Step 3 does require some changes to your subgraph schemas, described here.
Breaking changes
As mentioned above, the following Federation 1 examples should produce composition errors, but they aren't detected. If your subgraph schemas include syntax that matches any of these, you need to update those schemas before moving to Federation 2.
See breaking changes
Invalid @key
directives
An entity's @key
consists of one or more of the entity's own fields
. If any of these fields have subfields, the @key
must also include at least one of those subfields:✅
1type User @key(fields: "id organization { id }") {
2 id: ID!
3 organization: Organization!
4}
5
6type Organization {
7 id: ID!
8 name: String!
9}
User
's key fields are User.id
and User.organization.id
.Federation 1 composition incorrectly allows a @key
such as the following:❌
1type User @key(fields: "id organization") {
2 id: ID!
3 organization: Organization!
4}
5
6type Organization {
7 id: ID!
8 name: String!
9}
@key
should break composition because it doesn't include at least one subfield of Organization
.Invalid @requires
directives
A subgraph can mark an entity field with the @requires
directive to indicate that it depends on fields and subfields from another subgraph:✅
1type Product @key(fields:"sku") {
2 sku: ID!
3 dimensions: ProductDimensions!
4}
5
6type ProductDimensions {
7 size: Int!
8 weight: Int!
9}
1extend type Product @key(fields:"sku") {
2 sku: ID! @external
3 dimensions: ProductDimensions! @external
4 shippingEstimate: Int! @requires(fields: "dimensions { size weight }")
5}
6
7type ProductDimensions {
8 size: Int!
9 weight: Int!
10}
shippingEstimate
field depends on the dimensions.size
and dimensions.weight
fields of Subgraph A.Federation 1 incorrectly allows a @requires
directive such as the following:❌
1type Product @key(fields:"sku") {
2 sku: ID!
3 dimensions: ProductDimensions!
4}
5
6type ProductDimensions {
7 size: Int!
8 weight: Int!
9}
1extend type Product @key(fields:"sku") {
2 sku: ID! @external
3 dimensions: ProductDimensions! @external
4 shippingEstimate: Int! @requires(fields: "dimensions { length depth }")
5}
6
7type ProductDimensions {
8 size: Int!
9 weight: Int!
10}
@requires
directive should break composition because it depends on subfields of ProductDimensions
that don't exist (length
and depth
).Invalid @provides
directives
A subgraph can annotate an entity field with the @provides
directive to indicate that the subgraph can resolve entity fields normally marked as @external
on its own.✅
1type Product @key(fields: "id") {
2 id: ID!
3 info: ProductInfo @external
4}
5
6type ProductInfo {
7 name: String! @external
8 inStock: Boolean! @external
9}
10
11type Query {
12 outOfStockProducts: [Product!]! @provides(fields: "info { name }")
13 discontinuedProducts: [Product!]!
14}
Product.info.name
field when accessed through the outOfStockProducts
query. Any other path to Product.info.name
results in an additional subgraph call.Federation 1 incorrectly allows @provides
usage like the following:❌
1type Product @key(fields: "id") {
2 id: ID!
3 info: ProductInfo @external
4}
5
6type ProductInfo {
7 name: String! @external
8 inStock: Boolean! @external
9}
10
11type Query {
12 outOfStockProducts: [Product!]! @provides(fields: "info")
13 discontinuedProducts: [Product!]!
14}
@provides
directives usage should break composition because it does not specify which subfields of ProductInfo
it can resolve. This is correctly caught and surfaced as an error in Federation v2 but Federation v1 incorrectly allows this usage.Can Federation 1 compose my Federation 2 subgraph schemas?
No, not after you convert at least one subgraph schema to a true Federation 2 schema.
Federation 2 provides more flexible composition rules compared to Federation 1. After you modify your subgraph schemas to take advantage of this flexibility, your graph will no longer compose with Federation 1. You need to revert these changes to move back to Federation 1.
Does @apollo/gateway
v2 support Federation 1?
Yes. If you want, you can update your gateway's @apollo/gateway
library to its latest 2.x
version before you're ready to move your graph to Federation 2.
Your plugins and customizations for @apollo/gateway
0.x
will continue to work as expected in @apollo/gateway
2.x
.
Compatibility table
Router/Gateway version | Federation 1 Composition | Federation 2 Composition |
---|---|---|
Apollo Router Core v1.x | 🟢 | 🟢 |
@apollo/gateway v2.x | 🟢 | 🟢 |
@apollo/gateway v0.x (deprecated) | 🟢 | ❌ |