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
@shareableor@externalin 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:
|