Federation-specific GraphQL directives
Apollo Federation defines a collection of directives that you use in your subgraph schemas to enable certain features.
Importing directives
To use federated directives in a Federation 2 subgraph schema, apply the @link
directive with the following format to the schema
type:
extend schema@link(url: "https://specs.apollo.dev/federation/v2.0",import: ["@key", "@shareable"])
You can apply this directive to your existing schema
declaration if you have one, or to a new extend schema
declaration (as shown above).
Modify the import
array to include whichever federated directives your subgraph schema uses. The example above imports the @key
and @shareable
directives (which are used most commonly).
Make sure to include the @
in each directive name!
Renaming directives
If a federated directive's name matches one of your own custom directives, you can rename the federated directive with the following syntax:
extend schema@link(url: "https://specs.apollo.dev/federation/v2.0",import: [{ name: "@key", as: "@primaryKey"}, "@shareable"])
This example subgraph schema uses @primaryKey
for the federated directive usually named @key
.
Managing entities
@key
Designates an object type as an entity.
Valid locations: Object type definitions
type Product @key(fields: "id") {id: ID!name: String!price: Int}
Arguments
Name / Type | Description |
---|---|
| Required. A GraphQL selection set (provided as a string) of fields and subfields that contribute to the entity's primary key. Examples:
See also Advanced |
| If Most commonly, you set this to The default value is |
Managing shared fields
@shareable
Indicates that an object type's field is allowed to be resolved by multiple subgraphs (by default, each field can be resolved by only one subgraph).
Valid locations: Field definitions; Object type definitions
type Position {x: Int! @shareabley: Int! @shareable}
If applied to an object type definition, all of that type's fields are considered @shareable
:
type Position @shareable {x: Int!y: Int!}
See also Value types in Apollo Federation and Resolving another subgraph's field.
@inaccessible
Indicates that a field or type should be omitted from the gateway's API schema, even if it's also defined in other subgraphs.
Valid locations: Field definitions; Type definitions for objects, interfaces, and unions
type Position @shareable {x: Int!y: Int!z: Int! @inaccessible}
An @inaccessible
field or type is not omitted from the supergraph schema, so the gateway still knows it exists (but clients can't include it in operations).
If a type is marked @inaccessible
, all fields that return that type must also be marked @inaccessible
. Otherwise, a composition error occurs.
The @inaccessible
directive is helpful for adding a new field to a shared value type. Often when you add a value type field in one subgraph, composition fails because that field isn't resolvable in other subgraphs. This directive enables you to preserve composition while adding the field to your remaining subgraphs. When the rollout is complete, you can remove the @inaccessible
directive and begin using the field.
@override
Indicates that a field is now resolved by this subgraph instead of another subgraph where it's also defined.
Valid locations: Field definitions
type Product @key(fields: "id") {id: ID!inStock: Boolean! @override(from: "Products")}
You use @override
to migrate a field from one subgraph to another. In the example above, we're migrating the Product.inStock
field from the Products subgraph to the Inventory subgraph. The composed supergraph schema indicates that Product.inStock
is resolved by the Inventory subgraph but not the Products subgraph, even though the Products subgraph also defines the field.
You can apply @override
to a @shareable
field. If you do, only the subgraph you provide in the from
argument no longer resolves that field. Other subgraphs can still resolve the field.
For more information, see Migrating entities and fields.
Arguments
Name / Type | Description |
---|---|
| Required. The name of the other subgraph that no longer resolves the field. |
Referencing external fields
@external
Indicates that a particular subgraph can't resolve a particular object field in most cases, but the subgraph still needs to define that field for other purposes. Most commonly used in combination with @provides
and/or @requires
.
Valid locations: Field definitions
type Product @key(fields: "id") {id: ID!name: String! @externalinStock: Boolean!}type Query {outOfStockProducts: [Product!]! @provides(fields: "name")discontinuedProducts: [Product!]!}
The example subgraph above usually can't resolve the Product.name
field, but it can at the Query.outOfStockProducts
query path.
@provides
Indicates that a particular subgraph can resolve particular fields, but only at a particular query path.
Valid locations: Field definitions
type Product @key(fields: "id") {id: ID!name: String! @externalinStock: Boolean!}type Query {outOfStockProducts: [Product!]! @provides(fields: "name")discontinuedProducts: [Product!]!}
The example subgraph above can resolve Product.name
for products returned by Query.outOfStockProducts
but not Query.discontinuedProducts
.
If a subgraph @provides
a particular field that it can't always resolve:
- The subgraph must define that field and mark it as
@external
, as shown above. - That field must be marked as either
@shareable
or@external
in every subgraph that defines it.
Otherwise, a composition error occurs.
Arguments
Name / Type | Description |
---|---|
| Required. A GraphQL selection set (provided as a string) of object fields and subfields that the subgraph can resolve only at this query path. Examples:
|
@requires
Indicates that a particular object field's resolver requires the values of other fields that are resolved by other subgraphs.
Valid locations: Field definitions
type Product @key(fields: "id") {id: ID!size: Int @externalweight: Int @externalshippingEstimate: String @requires(fields: "size weight")}
The example subgraph above resolves a Product
object's shippingEstimate
field, but it requires the product's size
and weight
to do so. These two fields are resolved by a different subgraph, so they're marked as @external
.
See also Contributing computed entity fields.
Arguments
Name / Type | Description |
---|---|
| Required. A GraphQL selection set (provided as a string) of Examples:
|