GraphQL Schema Stability

27 February, 2024

2 min read

Last updated on 13 March, 2024

I work in a company which has 3 mature GraphQL API clients: web, IOS native and Android Native. We have more than 45 millions active customers and Schema Stability is a really important topic for us. For GraphQL Schema Stability we have specific field lifecycle.

In that post, however, I will list Breaking Changes for GraphQL API you should look after. There will be also code examples available to illustrate what I am talking about.

If you prefer video more, I have YouTube video on my channel about the same subject.

  • Removal of field or change a spelling for a field
diff --git a/schema.gql b/schema.gql
index f4c5362..c188b47 100644
--- a/schema.gql
+++ b/schema.gql
@@ -4,14 +4,13 @@ type Query {
 
 type ComplexType {
   compositeField: CompositeType!
-  scalarField: String
   enumField: EnumType
   fieldAcceptingArguments(args: InputType, requiredArg: Boolean!): String
 }
 
 input InputType {
   stringField: String
-  intField: Int
+  intField_: Int
   booleanField: Boolean
   enumField: EnumType
   nestedListField: [Int!]! # This list can't be null AND its list *items* can't be null

This is obviously breaking change and all clients would break if you push that to production. If you want to change spelling for a field for some reason, create another field with spelling you want - and gradually migrate all clients to use it.

  • Change of return type in field
diff --git a/schema.gql b/schema.gql
index c188b47..2c46251 100644
--- a/schema.gql
+++ b/schema.gql
@@ -10,7 +10,7 @@ type ComplexType {
 
 input InputType {
   stringField: String
-  intField_: Int
+  intField_: Float
   booleanField: Boolean
   enumField: EnumType
   nestedListField: [Int!]! # This list can't be null AND its list *items* can't be null

Your web client may not emit exceptions in some cases and show on the screen some components which were not affected, but your mobile client view would break completely. Native mobile apps use strictly typed languages and they can’t survive after you’ve pushed such a change.

  • Change of type in an argument from optional to strict
diff --git a/schema.gql b/schema.gql
index 2c46251..2c5ccb7 100644
--- a/schema.gql
+++ b/schema.gql
@@ -10,7 +10,7 @@ type ComplexType {
 
 input InputType {
   stringField: String
-  intField_: Float
+  intField_: Float!
   booleanField: Boolean
   enumField: EnumType
   nestedListField: [Int!]! # This list can't be null AND its list *items* can't be null

Both web and mobile clients would be broken after you do that. You can change strict arguments to optional safely, but not otherwise.

  • Adding a new required argument to a field
diff --git a/schema.gql b/schema.gql
index 2c5ccb7..1465eb5 100644
--- a/schema.gql
+++ b/schema.gql
@@ -5,7 +5,7 @@ type Query {
 type ComplexType {
   compositeField: CompositeType!
   enumField: EnumType
-  fieldAcceptingArguments(args: InputType, requiredArg: Boolean!): String
+  fieldAcceptingArguments(args: InputType, requiredArg: Boolean!, newRequiredArg: String!): String
 }
 
 input InputType {
  • Adding new variant to enum or union
diff --git a/schema.gql b/schema.gql
index 1465eb5..308dd93 100644
--- a/schema.gql
+++ b/schema.gql
@@ -24,4 +24,5 @@ type CompositeType {
 enum EnumType {
   ENUM_VALUE
   ANOTHER_ENUM_VALUE
+  NEW_ENUM_VALUE
 }

Most people don’t know about that and make this mistake frequently. Your JS web client may be okay with that, but strictly typed mobile clients may break. They need to know all enum and union variants during compile time.

You can prevent any breaking change to go to your production through linters. At Zalando we have our own set up, which I can’t share with you. There are a lot of open source alternatives. One of such is GraphQL Inspector from The Guild.

I will write on how to set up GraphQL Inspector for your codebase in my next post. If you want to read it, make sure you subscribe on my newsletter.

You can subscribe on my newsletters

Let's see if we can become internet friends.

Check also related posts

Troy Köhler

TwitterYouTubeInstagramLinkedin