Introducing the @configureDescription directive for GraphQL Federation
A few weeks ago, one of our customers came to us with an interesting problem: they wanted explicit and granular control over the descriptions that were propagated to their federated graph. As I'm sure you're aware, most constituents of a GraphQL schema may define a description; and an instance of a constituent (coordinates) could appear in multiple subgraphs—each with its own bespoke description. However, only one description can be propagated to the federated graph.
We're hiring!
We're looking for Golang (Go) Developers, DevOps Engineers and Solution Architects who want to help us shape the future of Microservices, distributed systems, and APIs.
By working at WunderGraph, you'll have the opportunity to build the next generation of API and Microservices infrastructure. Our customer base ranges from small startups to well-known enterprises, allowing you to not just have an impact at scale, but also to build a network of industry professionals.
The current state of federated descriptions
GraphQL Federation is a powerful tool that enables teams to compose a single API from multiple subgraphs. But despite all Federation's strengths, managing metadata such as field and type descriptions across a federated schema can still be... challenging.
If multiple subgraphs define conflicting descriptions for the same coordinates, should the federated graph use the first description it encounters? How about the one that's most recently defined? Or maybe the one that's longest? When and how should a description be overridden by another team? And should one team "own" a description? According to the Federation spec, you can't, like, own a description, man.
The current approach to propagating a description by WunderGraph Cosmo composition is simple: pick the longest description; in the event of a tie, pick the first encountered. Apollo takes a slightly more complicated approach that involves propagating the most frequent description among other nuances. But whatever the implementation, not all descriptions are created equal. And moreover, descriptions can serve completely different functions. For instance, a subgraph is typically "owned" by a single team. This team may want to document important information, comments, or explanations in their descriptions... Descriptions that may not necessarily be intended to be client-facing.
Moreover, instances of a schema constituent can also serve different purposes, which would mean a single description across subgraphs may not be helpful. Here's an example:
The description for Object.age
is useful for the owners of the subgraph... But it is not useful nor meaningful for the federated graph. And such a description could be unintentionally propagated if it "wins" the description-picking algorithm.
Descriptions are crucial for understanding an API and its capabilities. Inconsistent, redundant, or misleading descriptions can lead to confusion and errors for API consumers.
This is where the @openfed__configureDescription
directive comes in. It aims to solve these problems and more by providing schema designers fine-grained control over how descriptions are propagated, overridden, or even hidden from the federated graph.
You can dive straight into the documentation here , but this blog post will attempt to go into a little more detail.
The @openfed__configureDescription directive
The @openfed__configureDescription
directive is defined as follows:
Let's take a look at its four main functions:
- Propagating a description: Ensuring a specific description appears in the federated graph.
- Overriding a description: Replacing a defined description with a different one.
- Preventing the propagation of a description: Preventing a specific description from being included in the federated graph.
- Propagating a description through an extension type: Allowing extension types to define descriptions.
1. Propagating a description
In subgraph A, the description for User
is really only relevant for development and not consumption:
In subgraph B, the description for User
is much more suited to be propagated in the federated graph. This is accomplished by the addition of the @openfed__configureDescription
directive on the Object level:
The federated graph propagates the description as instructed by the @openfed__configureDescription
directive:
2. Override a description
In subgraph A, the description is again intended for internal development. However, User
is defined only in subgraph A... And we'd a rather a different and more helpful description be propagated to the federated graph. This is achieved by adding @openfed__configureDescription(descriptionOverride: ...)
on the Object level:
The federated graph propagates the description as instructed by the descriptionOverride
argument of the @openfed__configureDescription
directive:
3. Prevent the propagation of a description
In subgraph A, the description for User.name
is not intended to be public. Consequently, the @openfed__configureDescription
directive is added on the field with the propagate
argument set to false
:
In subgraph B, there is no description for User.name
at all:
As instructed by the @openfed__configureDescription
directive, the federated graph does not propagate any description for User.name
:
Without the @openfed__configureDescription
directive, the composition algorithm would have been forced to propagate the only available description—one that has no real merit in the federated graph.
4. Propagating a description through an extension type
Occasionally, schema designers have no choice but to use an extension type "orphan" ("orphan" here meaning no base type appears to be defined in the schema). This could be due to a number of reasons, e.g., framework limitations, multi-file schemas, or even legacy syntax. But as outlined in the GraphQL spec , extension types cannot define descriptions.
The @openfed__configureDescription
directive allows you to navigate such restrictions that are beyond your control. This is achieved by adding the directive on the Object level with the intended description provided to the descriptionOverride
argument.
In subgraph A, Query
is an extension type "orphan". However, the ability to define a description would be convenient to describe important behaviour:
In subgraph B, Query
is also an extension type "orphan".
As instructed by the @openfed__configureDescription
directive, the description provided to the descriptionOverride
argument is propagated to the federated graph:
In examples like the above, defining a description for an Object is made difficult due to whatever constraints prevent that Object's inclusion as a type definition in the schema. The openfed__configureDescription
directive offers flexibility in such situations, enabling you and your team to propagate specific descriptions to your federated graph without restriction.
Composition rules
The constraints for @openfed__configureDescription
are relatively simple:
- The coordinates that define the directive must define a description or provide a non-empty string to the
descriptionOverride
argument. - No two coordinates may define the
propagate
argument astrue
(the default value). However, any number of coordinates may define thepropagate
argument asfalse
.
Failure to comply with any of these constraints will produce a composition error. This ensures the use of the directive and the propagation of descriptions is explicit and collaborative.
Why does any of this matter?
Clean, well-maintained documentation is crucial for usability and adoption of a GraphQL API. By giving teams full control over descriptions in a federated setup, the @openfed__configureDescription
directive ensures consistency, helps prevents internal leaks, and allows flexibility through description overrides where necessary.
Final thoughts
The @openfed__configureDescription
directive is a powerful addition to GraphQL Federation, making it easier to manage descriptions across subgraphs. If you're working with federated schemas, consider adopting @openfed__configureDescription
to streamline your API documentation and enhance the developer experience. And when you do, we'd absolutely love to hear your feedback.
Have you faced challenges surrounding descriptions in a federated graph? What about other problems you and your team face that remain unsolved? Please discuss in the comments or reach out to us directly !
And lastly, if you enjoy solving interesting problems that come from real users of the product you're building, WunderGraph is currently hiring ! We look forward to reading your application! 😎