The @defer annotation is a useful but no spec compliant extension to graphql.
Today the semantics of how it should act are no specified. The original graphql-java implementation did not put many restrictions in place.
Apollo have added @defer support to their offering an documented its restrictions well.
https://www.apollographql.com/docs/react/features/defer-support.html#defer-usage
@defer can be applied on any FIELD of a Query operation. It also takes an optional argument if, that is a boolean controlling whether it is active, similar to @include.
@include and @Skip take precedence over @defer.
Mutations: Not supported.
Non-Nullable Types: Not allowed and will throw a validation error. This is because deferred fields are returned as null in the initial response. Deferring non-nullable types may also lead to unexpected behavior when errors occur, since errors will propagate up to the nearest nullable parent as per the GraphQL spec. We want to avoid letting errors on deferred fields clobber the initial data that was loaded already.
Nesting: @defer can be nested arbitrarily. For example, we can defer a list type, and defer a field on an object in the list. During execution, we ensure that the patch for a parent field will be sent before its children, even if the child object resolves first. This will simplify the logic for merging patches.
GraphQL fragments: Supported. If there are multiple declarations of a field within the query, all of them have to contain @defer for the field to be deferred. This could happen if we have use a fragment like this:
fragment StoryDetail on Story {
id
text
}
query {
newsFeed {
stories {
text @defer
...StoryDetail
}
}
}
In this case, text will not be deferred since @defer was not applied in the fragment definition.
A common pattern around fragments is to bind it to a component and reuse them across different parts of your UI. This is why it would be ideal to make sure that the @defer behavior of fields in a fragment is not overridden.
It makes sense for graphql-java to follow suit and put more semantics around how defer can be used.
The @defer annotation is a useful but no spec compliant extension to graphql.
Today the semantics of how it should act are no specified. The original graphql-java implementation did not put many restrictions in place.
Apollo have added @defer support to their offering an documented its restrictions well.
https://www.apollographql.com/docs/react/features/defer-support.html#defer-usage
@defer can be applied on any FIELD of a Query operation. It also takes an optional argument if, that is a boolean controlling whether it is active, similar to @include.
@include and @Skip take precedence over @defer.
Mutations: Not supported.
Non-Nullable Types: Not allowed and will throw a validation error. This is because deferred fields are returned as null in the initial response. Deferring non-nullable types may also lead to unexpected behavior when errors occur, since errors will propagate up to the nearest nullable parent as per the GraphQL spec. We want to avoid letting errors on deferred fields clobber the initial data that was loaded already.
Nesting: @defer can be nested arbitrarily. For example, we can defer a list type, and defer a field on an object in the list. During execution, we ensure that the patch for a parent field will be sent before its children, even if the child object resolves first. This will simplify the logic for merging patches.
GraphQL fragments: Supported. If there are multiple declarations of a field within the query, all of them have to contain @defer for the field to be deferred. This could happen if we have use a fragment like this:
In this case, text will not be deferred since @defer was not applied in the fragment definition.
A common pattern around fragments is to bind it to a component and reuse them across different parts of your UI. This is why it would be ideal to make sure that the @defer behavior of fields in a fragment is not overridden.
It makes sense for graphql-java to follow suit and put more semantics around how defer can be used.