Schema governance approaches for GraphQL

Isha
Walmart Global Tech Blog
5 min readAug 11, 2022

This post outlines a method we are using at Walmart to ensure that collision-free, standardized subgraphs are onboarded onto the federated gateway. Using our in-house “GraphQL Schema Governance Tool”, we eliminate various concerns ahead of time, during the development cycle, and before onboarding by using the graphql-schema-linter and GraphQL Voyager packages.

GraphQL federation

Before jumping into details about the governance tool, let’s review the basics of GraphQL federation.

GraphQL federation provides a single GraphQL API with multiple services at the backend, allowing different teams to work on their own schemas or subgraphs with their own services. These schemas can then be integrated together to form a supergraph. The task of combining the subgraphs is done by the “gateway” layer, which does not require much code.

In case there are modifications in any of the services, the front-end layer only queries the federated gateway and does not have to make changes to queries based on the services.

We analyzed some subgraphs that are being integrated into our federated gateway and observed some common issues with their design. These served as our inspiration to develop the GraphQL Schema Governance Tool. Some of these issues are listed below:

Inconsistent schemas

One of the challenges with federation is the difficulty in managing subgraphs from various sources. Teams may end up creating the same Type as another team, which can lead to conflicts after integration in the federated gateway.

Team A and Team B create the same Type Person which leads to conflict

Non-standard development practices

Continuous integration of subgraphs by different teams at the federated gateway increases the possibility of collision. Developers go through the entire Software Development Life Cycle (SDLC) before noticing the collisions (such as usage of the same Types) at the gateway.

Different datatypes used for the same field

Code quality assurance

The GraphQL schema needs to be analyzed for design guidelines. This process can be automated by using a tool that can parse the schema and return the problems with it.

Lack of a visual tool to analyze issues

As schema size increases, it can become difficult to identify accidental cyclic dependencies between Types. However, with a visual tool such as GraphQL Voyager, detecting cyclic dependencies can be easier and less time-consuming.

Cyclic dependency between Type Person and Type Contact

Complex graphs

From our analysis, we found that flattened graphs have lower response times compared to non-flat graphs. To avoid performance issues at the gateway level, identification of a complex graph can be made before integration.

Complex graph for Type Person

GraphQL Schema Governance Tool

To solve the above challenges, we developed the GraphQL Schema Governance Tool by leveraging the graphql-schema-linter and GraphQL Voyager packages.

The architecture of the GraphQL Schema Governance Tool

graphql-schema-linter

graphql-schema-linter is an npm package for validating the Schema Definition Language (SDL ) against certain rules. The package provides a command-line utility with a set of built-in rules and several configurations for validations. The utility parses the schema definitions and generates a report which can be configured into different formats (text/compact/JSON).

In addition to the built-in rules, the library also allows the developer to write a set of custom rules that can cater to their organization’s needs. For example, we used the following rules to ensure a valid, consistent schema:

The [C] indicates a custom rule that we developed.

  • Fields have descriptions
    This rule will validate that object type fields and interface type fields have descriptions.
  • Fields are camel-cased
    This rule will validate that object type field, and interface type field names are camel-cased.
  • Schema depth checker [C]
    This rule checks the depth of a schema by checking the type nesting. If the depth is greater than a certain threshold, it will throw an error.
  • Cycle detector [C]
    This rule will check for cyclic dependencies in the subgraph.
  • IDs should be of type ID [C]
    This rule throws a validation error if a field with an ‘id’ suffix is not of type ID.
  • Collision checker [C]:
    This rule will access and get a list of available types at the supergraph. It throws an error if any of the types in the subgraph are present in the supergraph.
  • Sparse array checker [C]
    For the type below, the inner exclamation point indicates that any value in the array will be a String. If this exclamation is missing, the array can contain null/undefined values. The outer exclamation indicates that an array will always be returned but may be empty.

This rule validates that for a non-nullable array, the field type inside the array is also non-nullable.

type Person {contacts: [String!]!}

After validating these rules, a report of all errors and warnings is sent to the schema owner.

The generated report

GraphQL Voyager

GraphQL Voyager is a package for interactive visualization of any GraphQL API. This is a great tool when designing or discussing your data model. It can be integrated with a GraphQL API and has the following features:

  • Quick navigation on graph
  • Left panel which provides more detailed information about every type
  • “Skip Relay” option that simplifies graph by removing relay wrapper classes
  • Ability to choose any type to be a root of the graph

A visualization of the knowledge graph is also sent to the schema owner. This visual enables the developer to understand issues with their schema faster.

Conclusion

From the above challenges, it is clear that a schema governance tool is necessary for a complex supergraph. This helps to ensure that federated schema design guidelines are being followed. In addition, the GraphQL Schema Governance Tool helped in achieving the following:

  • Gain insights into standard schema design practices
  • Understand schema conflicts before integration into the federation
  • Save time for reviewing and redoing development work in case of conflicts
  • Prevent performance issues by detecting complex graphs before integration

Big thank you to Rohit Magazine and Rupesh Patel for contributing to this article!

--

--