Strategies for versioning fields and directives
Please read first guide Evolving the schema via field versioning, which explains the "field versioning" feature in Gato GraphQL.
Gato GraphQL allows fields and directives to receive argument versionConstraint
, to choose what specific version (i.e. implementation) of the field/directive to use:
What should happen when we do not specify the versionConstraint
argument? For instance, to which version should field surname
in the query below resolve to?
We have two concerns here:
- Deciding which is the default version to use when none is provided
- Informing the client that there are several versions to choose from
Before tackling these concerns, we need to find out how well GraphQL provides contextual feedback when running a query.
Providing contextual feedback when running queries
We need to point out a less-than-ideal circumstance with GraphQL right now: it doesn't offer good contextual information when running queries. This is evident concerning deprecations, where deprecation data is shown only through introspection by querying fields isDeprecated
and deprecationReason
on the Field
and Enum
types:
The response will be:
However, when running a query involving a deprecated field…
...the deprecation information will not appear in the response:
This means that the developer executing the query must actively execute introspection queries to find out whether the schema was upgraded and any field deprecated. That may happen… once in a long while? Quite possibly never?
It would be a great improvement towards revising outdated queries if the GraphQL API provided deprecation information when executing queries that involve deprecated fields. This information may ideally be given under a new top-level entry deprecations
, appearing after errors
and before data
(following the spec's suggestion for the response format).
Since a deprecations
top-level entry is not part of the spec, Gato GraphQL's "Proactive Feedback" feature adds support for better feedback in the response to the query by using the wildcard top-level entry extensions
, which allows extending the protocol as needed:
Publicizing versions through warnings
We have just learnt that the GraphQL server can use the extensions
top-level entry to provide deprecations. We can use this same methodology for adding a warnings
entry, in which we inform the developer that a field has been versioned. We do not provide this information always; only when the query involves a field which has been versioned, and the versionConstraint
argument is absent.
Defining the default version for a field
There are several approaches we can employ, including:
- Make
versionConstraint
mandatory - Use the old version by default until a certain date, on which the new version becomes the default
- Use the latest version by default and encourage the query developers to explicitly state which version to use
Let's explore each of these strategies and see their responses when running this query:
versionConstraint
mandatory 1. Make
This is the most obvious one: forbid the client from not specifying the version constraint by making the field argument mandatory. Then, whenever not provided, the query will return an error.
Running the query will respond with:
2. Use the old version by default until a certain date on which the new version becomes the default
Keep using the old version until a certain date, when the new version will become the default. While in this transition period, ask the query developers to explicitly add a version constraint to the old version before that date through the new extensions.warnings
entry in the query.
Running the query could respond with:
3. Use the latest version and encourage the users to explicitly state which version to use
Use the latest version of the field whenever the versionConstraint
is not set, and encourage the query developers to explicitly define which version must be used, showing the list of all available versions for that field through a new extensions.warnings
entry:
Running the query could respond with:
Versioning directives
We can use the same strategies to version directives. For instance, when running the query without providing the version constraint:
It could assume a default version to use and produces a warning message for the developer to revise the query: