Marks a field or type as declared in this subgraph but resolved by another. Enables use in @requires
, @provides
, or interface implementations.
@external
directive marks a field or type that is declared in this subgraph but resolved by another subgraph.
The field may be resolved unconditionally or only in specific query paths, such as when used with @provides
.
Subgraphs use @external
to reference fields they don’t resolve directly—typically when using @requires
, @provides
, or to satisfy interface
contracts.
@external
may be required even when a field is technically resolvable.
@key
usage:
Fields in @key(fields: ...)
must be marked @external
if they are declared in the subgraph but resolved in another. This is especially true for entity extensions.
@requires
and @provides
:
All fields in these field sets must be marked @external
, regardless of whether they are leaf or non-leaf fields.
Validation:
In Federation v1, misconfigured @external
fields are often silently removed during composition, with no visible error.
@external
.
@key
usage:
Fields in @key(fields: ...)
do not need @external
unless they cannot be resolved in the subgraph.
@requires
and @provides
:
Only leaf fields, or parent fields explicitly listed in the same @requires
or @provides
field set string, must be marked @external
if they are declared in the subgraph but resolved in another.
A field set is the string argument passed to these directives, such as "user { email }"
.
Validation:
In Federation v2, @external
is only valid if the field is:
@key
, @requires
, or @provides
field set.interface
.@external
, known as a shared field instance. Otherwise, composition fails.
WunderGraph Cosmo helps validate @external
usage, especially in Federation v1 environments where misconfigurations can be harder to detect.
@external
directive:
@provides
).@key(fields: ...)
in Federation v1.@requires
and @provides
without triggering composition errors.@external
to:
@external
marks a field that is defined in this subgraph but resolved in another.
Whether and how the field resolves depends on the query path and the directives involved.
@external
when the field is unresolvable from the current subgraph and the field is referenced by:
@key(fields: "...")
(in Federation v1 only)@provides(fields: "...")
@requires(fields: "...")
OR the field is required to satisfy an interface
implemented by the type
@external
fields to fulfill an interface it implements from another subgraph.@external
field must have a matching, resolvable definition in another subgraph that is not marked @external
.
This creates a shared field instance—a field defined in one subgraph and referenced externally in another—that enables composition and cross-subgraph resolution.
@external
Means in Different Contexts@external
depends on context. It can indicate:
Meaning | Description |
---|---|
Unresolvable | The field cannot be resolved by the current subgraph |
Conditionally resolvable | The field is resolved only in certain paths (e.g., via @provides ) |
Legacy @key usage (v1) | The field is resolvable, but marked @external to satisfy a @key on an extension |
Interface satisfaction | The field is required to fulfill an interface but is resolved in a different subgraph |
@external
may appear in places that seem redundant or unnecessary, especially in Federation v1.
User.email
field is defined in the schema but only resolved by another subgraph.
This subgraph references it via @provides
.
@external
to a type marks all its fields as externally defined.
@external
only when needed for @requires
, @provides
, or @key
@external
usage with @key
on extensions (Federation v1)@external
field that is referenced by a @key(fields: ...)
field set on an extension definition must be explicitly marked.
This is considered legacy syntax, and the field is always resolvable by that subgraph in V1 and V2.
@external
, even if the subgraph could resolve them.
The field was always resolvable — @external
was simply part of the legacy composition model.
@external
on key fields in Federation v2@external
, but doing so implies that the field is not resolvable from the current subgraph.
If the field is actually resolvable, marking it @external
will cause satisfiability errors at composition time.
This is a common pitfall when migrating from v1: key fields marked @external
must remain resolvable in v2.
id
and upc
as @external
, but doesn’t actually provide a way to resolve them.
The router cannot satisfy queries that require navigating from A to B using these keys.
Product.id
is not resolvable from Subgraph A.@external
but no other subgraph defines and resolves that field, the composition process will fail.
Additionally, composition typically fails if a type has no locally defined fields — that is, if all of its fields are marked @external
.
Every type must own at least one field in the subgraph to be valid in the composed supergraph.
Otherwise, the router has no anchor point for resolution.
EXTERNAL_MISSING_ON_BASE
).
@external
on extended types@external
to a type does not automatically apply it to fields added later via extend
blocks.
This distinction is important when normalizing schemas across subgraphs.
city
is treated as @external
.
To ensure clarity and correctness, country
should be annotated directly:
@external
is often required, even when it’s not referenced by @requires
or @provides
, due to weaker validation and looser assumptions.
If you’re migrating from v1 to v2:
@external
usage carefully.@key
).@external
usage.@external
fields@external
without a matching, resolvable definition in another subgraph is removed during composition.
legacyTag
, it will not appear in the composed supergraph at all.
Cosmo emits a warning if it detects @external
fields that do not match a known definition elsewhere.
@external
, composition will fail if all fields of a type are marked @external
.
Use Case | Valid? | Notes |
---|---|---|
Field used in @requires or @provides | ✅ | Field must be unresolvable or conditionally resolvable |
Field satisfies an interface | ✅ | Always valid if required by the interface |
Field used in @key (v1, on extension) | ✅ | Legacy pattern — required even if resolvable |
Field used in @key (v2, on object) | ⚠️ | Only valid if truly unresolvable |
Type-level @external | ✅ | Applies to all fields on that type |
No non-external counterpart exists | ❌ | Invalid — triggers error (v2) or silent removal (v1) |
All fields on a type marked @external | ❌ | Invalid — the subgraph must define at least one field without @external |