Handling Breaking Changes in GraphQL

Requirements change, but API contracts are forever - I wish! A breaking change is something that is not backwards compatible. This means that a consumer of your API would not be able to use the new version without making a code change themselves. We avoid breaking changes if possible, but there are cases when they are inevitable. It could be something small: like making a mandatory field optional. Or it could be something big: like removing a query or a mutation. In this talk we'll review the types of breaking changes you may encounter and how to deal with them gracefully.

Rate this content
Bookmark
Slides
Video Summary and Transcription
Handling breaking changes in GraphQL schemas poses challenges, especially for mobile apps. A breaking change in GraphQL occurs when an update is not backwards compatible, which can cause previously functioning queries to fail. The use of the deprecated directive in GraphQL is crucial as it tags fields as deprecated, signaling to consumers that these fields should be phased out. The video emphasizes the importance of following the process of add, deprecate, migrate, remove to introduce changes safely. For mobile apps, timing is crucial due to delayed updates by users. Tools like GraphQL Inspector are highlighted for managing breaking changes, as they compare schemas in pull requests and identify disruptive updates. Changing a mandatory field to optional is a common breaking change. Monitoring query usage and client migrations can help assess the impact of changes. Strategies like in-app prompts are suggested to encourage user updates. The video also discusses the complexities of GraphQL versioning and how it affects API development.

FAQ

The deprecated directive in GraphQL is used to indicate that a field or type should no longer be used. It allows developers to provide a deprecation reason and helps clients understand that they should transition to using alternative fields or types.

A safe way to introduce breaking changes in a GraphQL API used by mobile apps is to ensure all users have migrated to newer app versions that support these changes. Using strategies like in-app upgrade prompts can encourage users to update their applications.

The GraphQL Inspector tool is beneficial for managing breaking changes in GraphQL APIs. It provides functionalities like pull request checks to identify breaking changes, ensuring that updates do not unintentionally disrupt existing functionalities.

A breaking change in a GraphQL schema is an update that modifies the API contract in a way that is not backwards compatible, causing a previously functioning query to fail because of the changes.

Handling breaking changes in mobile applications is challenging because not all users update their apps immediately. This delay can prevent a uniform shift to new app versions, risking some users experiencing app failures if the API changes are not backward compatible.

To handle a breaking change, you can use the 'add, deprecate, migrate, remove' process. Start by adding new fields, deprecating old ones, migrating client applications to use the new schema, and finally removing the deprecated fields once all clients have migrated.

1. Introduction to Breaking Changes in GraphQL Schema#

Short description:

Hello everyone, in this part, I will talk about handling breaking changes in a GraphQL schema. I will explain what a breaking change is and provide a code example to illustrate it. Let's get started!

Hello everyone, it is a pleasure to be here and it is a pleasure to talk about something that is very relevant to my work, which is handling breaking changes in a GraphQL schema.

So, just a quick intro about me. My name is Kadi Kraman, I'm currently the Director of Mobile Development at Formidable. If you've not heard of us, Formidable is a consultancy. We build websites, mobile apps, and of course, GraphQL APIs. In my five years in this company, I think almost every single project had a GraphQL API in it. So we've been doing this quite a bit. Back in 2002, my first GraphQL API was around 2017, and since then, I've worked with both small and large applications, and mostly as an API consumer.

So, because I build a lot of mobile applications, usually I've been the client of a GraphQL API. I would spend maybe 20 per cent of my time writing GraphQL, and 80 per cent of my time using GraphQL APIs. So, breaking changes is something that's very relevant to me because I'm the client that gets affected if breaking changes happen.

So, what is a breaking change? A breaking change in a GraphQL schema is basically an update that causes the API contract to change in a way that is not backwards compatible. Now, what does this actually mean? I'm going to show you using a code example. So, here we have a little schema. We have a query where you can query a user by an ID and it will return you a user type. And the user type has just the ID and the name in it. Both of them are mandatory fields. And if we look at what a query would look like. So, here on the right, we're going to query the user by ID, query the ID and the name, and we get exactly that data back. So, say that you had this user type in your current project and the client comes back to you and says, hey, we don't want to have our name as a single string. We want to have the first name and the last name separately. So, as a new requirement, you need to separate the name field into first name and last name. So, how would you go about it? You would be tempted to do something like this. So, here we've added the first name and last name which are both mandatory strings. But then, because we really don't use the name anymore, we can remove the name field. Now, this seems all well and good from the schema side, from the API side. When we look at the client side and query the same query that we did before, we are actually met with an error. And the error says cannot query field name on type user. And indeed, the name field no longer exists. Now, this is an example of a breaking change.

2. Handling Breaking Changes in GraphQL Schema#

Short description:

A change that is not backwards compatible. Instead of deleting the field, we can add a deprecation notice using the deprecated directive. The deprecated directive allows you to tag a field in a schema as a deprecated field to communicate to your consumers that this field should no longer be used. It is part of the GraphQL spec and most GraphQL servers should be implementing it. Insomnia, a GraphQL client, provides an example of how deprecated fields are displayed in the schema. Now I will show you a way to introduce a breaking API change in a GraphQL API relatively safely by following the steps: add, deprecate, migrate, remove.

A change that is not backwards compatible. Because a query that worked on the previous version of this API no longer works because of this change. Let's look at how we would make this change backwards compatible. It's actually surprisingly simple. Instead of deleting the field, we can add a deprecation notice using the deprecated directive. Here you've seen next to the name field, I've added deprecated and also provided a reason. So in this case, it's deprecated in favor of first name and last name.

And here we can see that the previous query that queried just the ID and name still works and the new query that queries the first name and last name still works. Therefore, because both the previous and new queries work, this is a change that is backwards is compatible. The deprecated directive is really handy. It's basically it allows you to tag a field in a schema as a deprecated field to communicate to your consumers that this field should no longer be used. It is part of the GraphQL spec, which means that most GraphQL servers should be implementing it. The most important part, most IEDs, GraphQL tools, and clients that you might be using will pick up this notification and warn you if you're using a deprecated field.

Here I've added an example. This is from Insomnia, which is a GraphQL client that I use for querying. When I look at the schema and the user type in particular, we can see that the name now has an exclamation mark next to it. If I hover over it, it's telling me that the field name is now deprecated, and it's also giving me the deprecation message that I wrote. So it's deprecated in favor of first name and last name. Now there might be a reason, however, rarely, that you'd simply have to introduce a breaking API change. So I'm going to show you a way that you could introduce a breaking API change in a GraphQL API relatively safely. The key words you need to remember are add, deprecate, migrate, remove. Unfortunately, not a very good acronym. Let's go through these one by one to show you what each step means. So this is our starting state. We're going to start with this user type that we used before, just with the id and a name. And this is our application stack. So we're going to have a website, let's say that's an Xjs app. We're going to have an API. It's of course a GraphQL API. And because I build mobile apps, we're going to have a React Native app for iOS and Android in a third repository.

3. Deploying GraphQL API and Mobile Apps#

Short description:

All three repositories are deployed separately. The first version of web1, api1, and app1 implement the user type. The stages include adding schema fields, deprecating fields, releasing a new version of the API, migrating clients, and removing deprecated fields. Deploying mobile apps is more complex, with different versions being released to stores and a gradual transition of users.

So all three of these are in separate repositories and they are deployed separately. And the first version of these web1, api1, and app1 all implement the user type as seen here.

Now the first stage add is pretty straightforward. We're going to add the schema fields that need to be added. In this case, we're going to add the first name and last name to the user type.

The next stage deprecate, you would usually do it together with add. But in this one, we're going to deprecate any fields we might want to remove in the future. Here we've added the deprecated directive. We use the deprecated directive to add a deprecation notice to the name field in the user type.

Now when we're finished with all our changes, we will release a new version of the GraphQL API to api2. Now, api2 is still compatible with app1 and web1 which means this is a backwards compatible change.

The next step is the migration step. Now in this step, you have to go through all the clients, everything that's using your GraphQL API, and update them to use the new API. Then we'll go to the Website and the app. We'll do the change and we'll publish the new versions and ensure all of our users are using them.

Now when you're confident that no-one is using web1 and app1 any more, and you've published web2 and app2, then it might be safe to remove the field. So here we can remove the name field that was deprecated from the user type and when we're finished we will deploy the new version of the API to api3. Now api3 is not compatible with web1 and app1, they would still get an error, but if no-one is using them, you've already published the change, they will be using web2 and app2, then that is a fine deletion to make.

Now because I build mobile apps, I wouldn't be a mobile app developer if at this point I didn't go on a tangent on why this is so much harder on mobile applications. On a higher level, this is what deploying websites and APIs looks like. You've finished your version 1, you're going to upload it to wherever you release it, say AWS, it will become available to users, and 100% of your users are going to use it.

Now when it comes to releasing v2, when you finish coding it, you're going to upload it to AWS, you're going to make it available and instantly all of your users are going to switch over and 100% of your users will be using v2 and no one will be using v1. When you finish v3, you'll release it, 100% of your users will immediately be switching over.

Now this seems pretty obvious but the fact is, this isn't at all how it works for mobile applications. This is what deploying a mobile app looks like. When we've finished our v1, we're going to upload it to the stores, we're going to get an approval, and when we've got the approval we can publish it to the app and play store. And because it's the first ever version of our app, 100% of our users are going to be using it.

Next, when we're ready for v2, we're going to release it to our stores, we're going to get it approved, we're going to release it to our stores. We're going to, it actually takes time so we're going to go away for two weeks, we're going to look at the stats after two weeks, and we'll see that maybe 60% of the users will use it, will be using it. And 40% of users are still using v1.

4. Mobile App Release Adoption#

Short description:

Mobile app releases never get 100% adoption like websites do. Apps only get updated if the user has automatic updates turned on or if they manually update from the store listing page. There can be a significant delay between publishing the app and users actually getting the update.

And when we do another version, v3, we get it approved, we release it to the stores, we go away and come back after two weeks, we'll find that maybe 65% of the users are using it. 30% of users are still on v2 and 5% of the users are still on v1. Now the sad truth is that mobile app releases never get 100% adoption like websites do. And the reason for that is apps only get updated if the user either has automatic updates turned on, or if they go to the store listing page and update manually. Even if the user has automatic updates turned on, the update wouldn't be instant, as soon as the app is available, it will get updated. Instead, usually it will get updated once you plug in your phone and you connect it to the Wi-Fi. So there might be a huge delay between when you publish the app, and the users, even those who are first in line, actually get it.

5. Making Safe Upgrades in Mobile Apps#

Short description:

It's never safe to make a breaking change in a mobile app, but there are ways to make the upgrade as safe as possible. Building in a fail-safe prompt for users to upgrade is a last resort. Monitoring query usage and active users can help assess the impact of the breaking change. Break-in API changes are more significant for mobile apps than websites. Changing a mandatory field to optional in a GraphQL schema is a breaking change. This can be seen in a code example using TypeScript.

Knowing that, you might be asking, when is it safe to make a breaking API change, if it's used by a mobile application? Well, the truth that you don't want to hear, is that it's actually never safe to make such a breaking change. Because you will always affect someone, it is impossible to get 100% of your users, once your latest version.

But, what if I really really really have to? Well, there are ways to make this upgrade as safe as possible. Usually in mobile apps, we build in, so this is something you would have to build in as a developer, we would build in a fail-safe, which basically is a prompt that would prompt users to upgrade, if they want to continue using the app. Generally, most apps have it built in, but it is a last resort, we don't want to use it, it should never be part of your normal development flow because it's terrible UX and users hate it, and to be honest, Apple also hates it, and we don't want to piss off Apple.

As I was actually working on this talk, one of the apps that I use regularly had this app upgrade prompt, so I've added it here as an example. Basically, when I open the app, I will immediately get a native alert that says, this version is deprecated, please go to the store to upgrade it. So if I press on learn more, it will take me to the app store, where it will prompt me to upgrade. I've actually seen they did a complete revamp of the whole application. I think they rewrote it, so presumably, the previous version is no longer compatible. Now, even when you get to this point, and you've prevented users from using the old version of your app, you technically can't even then be sure that they're going to upgrade. Because at this point, I can choose to not press the update button on the app store because maybe I'm not on Wi-Fi and I don't want to use my mobile data. And also I can just decide that this annoys me and I'm going to use this app on the website instead, or not use it at all. And once you've done everything you can to make sure that users will update, then you just need to monitor that they are doing so. You'll do this in two levels. One is on the API side and one is on the app side. So on the API side, this will be maybe an AWS or in CoreLogix. You can generate metrics to monitor query usage. So you can generate a metric to monitor the usage of deprecated fields and you'll see whether or not they get called or not. And then on the other side, you can also monitor your apps are active users for each app version to kind of get an idea of the number of users still using app versions that are deprecated and that have this break-in change and how many users this break-in change could affect. And one thing to note is that having break-in API changes generally is much more significant for mobile app users and developers than it is for web users and developers. Because on the website, if your website goes down or it doesn't work, then usually your users could tweet at you, they could maybe email your customer service angrily, whereas if an app is broken, if the API doesn't work, then users have a very nice and convenient way to complain about it and they will do it in a store listing page and give you a one-star rating because of a single-line change where your API didn't work. Going away from that dreary topic, let's play a little game. Which one of these is a breaking change? So we've got the user type with the ID and a name, and on one side I've made the name from mandatory to optional, and on the other side I've made it from optional to mandatory. Did you see the first one? Indeed, in a GraphQL schema if you have a field that is mandatory and then you change it to be optional, that is a breaking change. And why is that? Well, it might not be very easy to see it from the schema, but it will be a little bit simpler to see as a code example. So here is, I've used TypeScript just to make it a little bit more obvious. And on the left, we have some code that you might have on the front end that uses this API. So because our user only has an id and a name, I might have a utility function that uses the name and takes the first parts of it as the first name. Now after I've done the change, so I made the name from mandatory to optional.

6. Detecting and Handling Breaking Changes#

Short description:

TypeScript helps detect null values, which can cause JavaScript errors. Changing the user ID from mandatory to optional or vice versa is a breaking change. GraphQL Inspector is a useful tool for detecting breaking changes in pull requests. It compares the current and working branch schemas, highlighting any changes. Removing types is always a breaking change. Adding an approved label to a pull request allows CI to pass even with a breaking change. Breaking schema changes include renaming, deleting, changing data types, and altering field requirements. Avoid breaking changes, especially for mobile and desktop apps. Use the add, deprecate, migrate, remove step to minimize user impact. Check out GraphQL Inspector to enhance your GraphQL API workflows.

So it might return null. Actually, TypeScript is helping me out and telling me that I can't call split on the user's name because it might be null. And indeed, if at any point the user name returns null, I would get the JavaScript error calling this function.

Let's do one more. In this case, I've got the user query and I'm changing the user ID that I'm querying it by from mandatory to optional or optional to mandatory. Did you see the second one? Yes, the second change is breaking. And it can be confusing because it's the opposite for query inputs because here, changing the user ID from optional to mandatory is breaking, not the other way around. I've used the diffs here on purpose so you can see that as a reviewer it is actually really easy to miss these kinds of changes.

Thankfully, there is a tool to help you. If you haven't checked it out yet, I would definitely recommend looking at GraphQL Inspector. We're currently using it on my project and it's made a huge difference. It does a bunch of things, but the most important thing for us is that it allows us to have a check on pull requests, which will tell us if a breaking API change will be introduced. You can use this on any kind of CI. We use GitHub Actions, so I'm going to show that as an example. Here what we're configuring is that it's going to compare the GraphQL schema in the current to the GraphQL schema in your current working branch. This is what it looks like on the actual pull request. On the left, we're going to see an example of a breaking change, so we have it set to fail CI, if there's a breaking change. And you can see the two types are being removed. Removing types is always a breaking change, and therefore this gets highlighted. And the other cool thing is actually on the right, we can see some examples of just kind of information notices. So these are not errors or warnings, it's just for information. And what the GraphQL inspector does is that it highlights any changes, so this will draw the attention of the reviewer to what's actually changed. And this is really important because you have to be quite aware of what you're actually adding to your GraphQL API, because as you can see on the other side, removing anything is always a breaking change. So once you add it, removing it could be a FAF. Because we've enabled fail on breaking, there's another thing that we've added, which is to have an approved label. So you can set your own label for an approved breaking change, so you can call us whatever we want, but this is us. So basically, if you add this label to a pull request, then even if it had a breaking change, it will allow the CI to pass. And this is really useful because basically, as a pull request gets introduced, a reviewer will go through it and they get highlighted that there is a breaking change, and a conversation needs to happen whether this is a change that we're happy to have in, is there another way to do it, and should be avoided altogether.

In summary, we looked at what is a breaking schema change. So this is renaming a field, deleting a field, changing the data type, making a required field optional, or making an optional input required. In general, you should avoid making breaking changes as much as possible, especially if your API is being used by a mobile application, or any kind of desktop application that doesn't have the same kind of publish workflow as websites and APIs. But if you do need to introduce a breaking change, you can use the add, deprecate, migrate, remove step to minimize the amount of users you're going to affect. And finally, if you haven't yet, I would very much recommend you check out GraphQL Inspector to improve your GraphQL API workflows.

Kadi Kraman
Kadi Kraman
22 min
08 Dec, 2022

Comments

Sign in or register to post your comment.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

From GraphQL Zero to GraphQL Hero with RedwoodJS
GraphQL Galaxy 2021GraphQL Galaxy 2021
32 min
From GraphQL Zero to GraphQL Hero with RedwoodJS
Top Content
Tom Pressenwurter introduces Redwood.js, a full stack app framework for building GraphQL APIs easily and maintainably. He demonstrates a Redwood.js application with a React-based front end and a Node.js API. Redwood.js offers a simplified folder structure and schema for organizing the application. It provides easy data manipulation and CRUD operations through GraphQL functions. Redwood.js allows for easy implementation of new queries and directives, including authentication and limiting access to data. It is a stable and production-ready framework that integrates well with other front-end technologies.
Local State and Server Cache: Finding a Balance
Vue.js London Live 2021Vue.js London Live 2021
24 min
Local State and Server Cache: Finding a Balance
Top Content
This Talk discusses handling local state in software development, particularly when dealing with asynchronous behavior and API requests. It explores the challenges of managing global state and the need for actions when handling server data. The Talk also highlights the issue of fetching data not in Vuex and the challenges of keeping data up-to-date in Vuex. It mentions alternative tools like Apollo Client and React Query for handling local state. The Talk concludes with a discussion on GitLab going public and the celebration that followed.
Get rid of your API schemas with tRPC
React Day Berlin 2022React Day Berlin 2022
29 min
Get rid of your API schemas with tRPC
Today's Talk introduces TRPC, a library that eliminates the need for code generation and provides type safety and better collaboration between front-end and back-end. TRPC is demonstrated in a Next JS application integrated with Prisma, allowing for easy implementation and interaction with the database. The library allows for seamless usage in the client, with automatic procedure renaming and the ability to call methods without generating types. TRPC's client-server interaction is based on HTTP requests and allows for easy debugging and tracing. The library also provides runtime type check and validation using Zod.
Batteries Included Reimagined - The Revival of GraphQL Yoga
GraphQL Galaxy 2021GraphQL Galaxy 2021
33 min
Batteries Included Reimagined - The Revival of GraphQL Yoga
Envelope is a powerful GraphQL plugin system that simplifies server development and allows for powerful plugin integration. It provides conformity for large corporations with multiple GraphQL servers and can be used with various frameworks. Envelope acts as the Babel of GraphQL, allowing the use of non-spec features. The Guild offers GraphQL Hive, a service similar to Apollo Studio, and encourages collaboration with other frameworks and languages.
Rock Solid React and GraphQL Apps for People in a Hurry
GraphQL Galaxy 2022GraphQL Galaxy 2022
29 min
Rock Solid React and GraphQL Apps for People in a Hurry
The Talk discusses the challenges and advancements in using GraphQL and React together. It introduces RedwoodJS, a framework that simplifies frontend-backend integration and provides features like code generation, scaffolding, and authentication. The Talk demonstrates how to set up a Redwood project, generate layouts and models, and perform CRUD operations. Redwood automates many GraphQL parts and provides an easy way for developers to get started with GraphQL. It also highlights the benefits of Redwood and suggests checking out RedwoodJS.com for more information.
Adopting GraphQL in an Enterprise
GraphQL Galaxy 2021GraphQL Galaxy 2021
32 min
Adopting GraphQL in an Enterprise
Today's Talk is about adopting GraphQL in an enterprise. It discusses the challenges of using REST APIs and the benefits of GraphQL. The Talk explores different approaches to adopting GraphQL, including coexistence with REST APIs. It emphasizes the power of GraphQL and provides tips for successful adoption. Overall, the Talk highlights the advantages of GraphQL in terms of efficiency, collaboration, and control over APIs.

Workshops on related topic

Build with SvelteKit and GraphQL
GraphQL Galaxy 2021GraphQL Galaxy 2021
140 min
Build with SvelteKit and GraphQL
Top Content
Featured WorkshopFree
Scott Spence
Scott Spence
Have you ever thought about building something that doesn't require a lot of boilerplate with a tiny bundle size? In this workshop, Scott Spence will go from hello world to covering routing and using endpoints in SvelteKit. You'll set up a backend GraphQL API then use GraphQL queries with SvelteKit to display the GraphQL API data. You'll build a fast secure project that uses SvelteKit's features, then deploy it as a fully static site. This course is for the Svelte curious who haven't had extensive experience with SvelteKit and want a deeper understanding of how to use it in practical applications.

Table of contents:
- Kick-off and Svelte introduction
- Initialise frontend project
- Tour of the SvelteKit skeleton project
- Configure backend project
- Query Data with GraphQL
- Fetching data to the frontend with GraphQL
- Styling
- Svelte directives
- Routing in SvelteKit
- Endpoints in SvelteKit
- Deploying to Netlify
- Navigation
- Mutations in GraphCMS
- Sending GraphQL Mutations via SvelteKit
- Q&A
Build Modern Applications Using GraphQL and Javascript
Node Congress 2024Node Congress 2024
152 min
Build Modern Applications Using GraphQL and Javascript
Featured Workshop
Emanuel Scirlet
Miguel Henriques
2 authors
Come and learn how you can supercharge your modern and secure applications using GraphQL and Javascript. In this workshop we will build a GraphQL API and we will demonstrate the benefits of the query language for APIs and what use cases that are fit for it. Basic Javascript knowledge required.
End-To-End Type Safety with React, GraphQL & Prisma
React Advanced 2022React Advanced 2022
95 min
End-To-End Type Safety with React, GraphQL & Prisma
Featured WorkshopFree
Sabin Adams
Sabin Adams
In this workshop, you will get a first-hand look at what end-to-end type safety is and why it is important. To accomplish this, you’ll be building a GraphQL API using modern, relevant tools which will be consumed by a React client.
Prerequisites: - Node.js installed on your machine (12.2.X / 14.X)- It is recommended (but not required) to use VS Code for the practical tasks- An IDE installed (VSCode recommended)- (Good to have)*A basic understanding of Node.js, React, and TypeScript
GraphQL for React Developers
GraphQL Galaxy 2022GraphQL Galaxy 2022
112 min
GraphQL for React Developers
Featured Workshop
Roy Derks
Roy Derks
There are many advantages to using GraphQL as a datasource for frontend development, compared to REST APIs. We developers in example need to write a lot of imperative code to retrieve data to display in our applications and handle state. With GraphQL you cannot only decrease the amount of code needed around data fetching and state-management you'll also get increased flexibility, better performance and most of all an improved developer experience. In this workshop you'll learn how GraphQL can improve your work as a frontend developer and how to handle GraphQL in your frontend React application.
Build a Headless WordPress App with Next.js and WPGraphQL
React Summit 2022React Summit 2022
173 min
Build a Headless WordPress App with Next.js and WPGraphQL
Top Content
WorkshopFree
Kellen Mace
Kellen Mace
In this workshop, you’ll learn how to build a Next.js app that uses Apollo Client to fetch data from a headless WordPress backend and use it to render the pages of your app. You’ll learn when you should consider a headless WordPress architecture, how to turn a WordPress backend into a GraphQL server, how to compose queries using the GraphiQL IDE, how to colocate GraphQL fragments with your components, and more.
Relational Database Modeling for GraphQL
GraphQL Galaxy 2020GraphQL Galaxy 2020
106 min
Relational Database Modeling for GraphQL
Top Content
WorkshopFree
Adron Hall
Adron Hall
In this workshop we'll dig deeper into data modeling. We'll start with a discussion about various database types and how they map to GraphQL. Once that groundwork is laid out, the focus will shift to specific types of databases and how to build data models that work best for GraphQL within various scenarios.
Table of contentsPart 1 - Hour 1      a. Relational Database Data Modeling      b. Comparing Relational and NoSQL Databases      c. GraphQL with the Database in mindPart 2 - Hour 2      a. Designing Relational Data Models      b. Relationship, Building MultijoinsTables      c. GraphQL & Relational Data Modeling Query Complexities
Prerequisites      a. Data modeling tool. The trainer will be using dbdiagram      b. Postgres, albeit no need to install this locally, as I'll be using a Postgres Dicker image, from Docker Hub for all examples      c. Hasura