@shareable Directive
The @shareable
directive is a federation V2-only directive. Examples and usages are outlined herein.
Definition
FIELD_DEFINITION declaration
If the @shareable
directive is declared on a field definition, the same field can be defined on the same named type from multiple subgraphs. All subgraphs that define a field in this way must be be capable of resolving that field. The resolver should also be identical across the subgraphs. For example:
In the example above, two subgraphs define the type User
with the field id
. This is valid because id
has been declared @shareable
; i.e, that the field id
can be resolved from multiple subgraphs.
OBJECT declaration
If the @shareable
directive is declared on an object type, all fields currently* defined on that type will be declared @shareable
. This is the same as declaring the @shareable
directive separately on each current* field definition.
*If an object is extended, unless a field definition on the object extension is explicitly declared @shareable
, it will not be considered shareable on the original object. This is true even if that object was originally declared @shareable
. An example is shown below:
In the example above, the User
object has been declared @shareable
. However, the first extension with the field age is not declared @shareable
. The second extension with the field id is declared @shareable
.
Consequently, when these extensions are applied, the OBJECT location @shareable
declaration is no longer applied, and the declarations are moved only to the relevant fields. This produces the normalized User
type where name
and id
are shareable but age
is not.
Federation V1 subgraphs and shareable
By default, all field definitions in a V1 subgraph are treated as shareable
. For example:
In the example above, the V1 subgraph cannot declare anything as @shareable
(this directive is V2 exclusive). Consequently, for compatibility with V2 subgraphs, it is considered shareable by default. However, any V2 subgraph that declares a field that exists on the same type in another subgraph must declare the @shareable
directive on the object or on that field definition. Failure to do so will lead to a composition error.
Entity keys and shareable
Fields that comprise part of at least one of the entity's primary keys are automatically considered shareable. For example:
In the example above, id
is part of at least one of the entity's primary key. Consequently, id
is automatically considered shareable without any further declaration. However, the field name, which is not part of a primary key, must be declared with the @shareable
directive.
Shared root type fields: resolving differently defined objects
Caveat: It is highly recommended only to use entities to resolve an object type over multiple subgraphs.Imagine we have the following two subgraphs:
These subgraphs will fail to produce a federated graph. This is because the field age
cannot be resolved for Friend
when querying friends from subgraph-1.
If a non-entity object type is defined differently across subgraphs, there is only one solution that ensures the type is always fully resolvable: shared root type fields.
In the example above, each subgraph that differently defines the type Friend
should include all root type fields that can resolve Friend
. Consequently, the following changes would allow a federated graph to be composed:
First, the Query.friends
root type field defined in subgraph-1 is declared @shareable
; i.e., it can be resolved from multiple subgraphs. Next, this shareable root type field is added to subgraph-2. Now it is possible to resolve all fields of Friend
from the Query.friend
root type field.
Note that all such root type fields that can resolve Friend
(be it nested or otherwise) would need to be defined (with @shareable
) in each subgraph.