44. GraphQL's Benefits and Costs
Hosted by Owen Ou, with guest Tanmai Gopal.
GraphQL is a querying language with the aim of increasing the productivity of frontend and backend developers. It can make working with React easier, be used as an API for third-party clients, and allow for feature-rich applications to request precisely the data they need. Like any part of your stack, GraphQL isn't a panacea. The language is still being developed, and has some limitations. Tanmai Gopal, the CEO of Hasura, guides us through the pros and cons of using GraphQL in your application.
Owen Ou, an engineer at Heroku, is joined by Tanmai Gopal, the CEO of Hasura. They start their conversation by describing what GraphQL is, and what problems it set out to solve. GraphQL focuses on making data fetching easier, whether that client is a web browser or an API call. GraphQL provides one endpoint that can query all your application's domain logic. If your primary consumer of data is a front end application, then GraphQL is likely a good choice to use.
The conversation continues with help on how to get started using GraphQL, and situations where GraphQL might not be useful. For example, if your data is not in JSON, or is in a binary format, it might not be a good fit. As well, depending on whether your application is a monolith or a set of microservices, how GraphQL incorporated varies, and can be difficult. Tanmai continues with his team's experience of incorporating GraphQL, the challenges they faced, and the improvements they noticed.
Tanmai and Owen conclude by looking to the future of GraphQL. The language is very solid, but the spec is continuing to evolve with community feedback.
Links from this episode
Owen: Hello, welcome to the Code[ish] podcast. My name is Owen Ou. I'm an engineer from Heroku. With me today we have Tanmai Gopal, a CEO from a company called Hasura. Today we are going to talk about GraphQL. So what is GraphQL and what is the motivation behind it?
Tanmai: GraphQL is an API specification, very similar to REST and very similar to SOAP before that, and it's an API specification that focuses on making data fetch kind of API calls easy, especially for front end applications. It is a specification that is agnostic to language or framework and even protocol, so you can implement a GraphQL on top of HTTP or something else, and you can implement a GraphQL server and a GraphQL client in any language in any framework. And it is independent to that. Again, very similar to the way REST and SOAP work. The key motivation behind GraphQL was to make it easier for front end developers and application developers to make API calls and to fetch data from API calls. There are some nuances around that and I can dive deeper, but it was primarily designed for application developers to be able to build quickly and to be able to integrate APIs and use APIs inside their applications faster.
Tanmai: Yeah, I'm talking about browser applications or I'm talking about web applications and mobile applications. In fact, GraphQL first started getting used in Facebook for the iOS application, so even for mobile applications, but basically developers were building front end, user facing applications. It was primarily designed for them, but GraphQL just like any other API can technically use any client and server, but you can see direct features in the design that make it very suitable for front end applications.
Owen: Got it. So GraphQL would be another one that I consider if I implement my client application. So maybe before comparing REST with GraphQL, what would be the cost and benefit of implementing GraphQL?
Tanmai: So there are technical costs and benefits of course to implementing GraphQL. But one of the most important motivations or I think the primary benefit to GraphQL and where GraphQL shines is going to be where you are building a web API, and the consumers of your API are mostly going to be front end applications. So that's the case that you would think about saying, "Well, maybe I don't expose a REST API but maybe I expose a GraphQL API", and the reason why this has a tremendous amount of benefit is because as a front end developer, if I wear the shoes of a front end developer, I love building out the application. I love caring about the user experience. I love making sure that users love the product that I build. But the part that I hate is the part where I need to integrate APIs to actually make the application work. And this bit is painful because traditionally with APIs, if you just think about integrating an API, the first thing is that most modern applications today, the same screen that you look at, the same webpage or the same mobile screen that you're looking at you actually make a variety of API calls to different things.
Tanmai: Maybe, you're making a SaaS API, API call to a SaaS service, maybe you're making an API call to your own web server. You're fetching different kinds of resources. Let's say for example, you're building a profile page. You need to make an API call to fetch the user information, like the username and email, and then maybe you need to make another API call to fetch the address information. You want to show the last five addresses of this user on their profile page. So you make another API call for doing that and soon you realize that for pages that are becoming complicated, you realize that you as a front end developer start making lots of API calls and this process is painful, because API calls are asynchronous, so you make an API call, you wait for the network to give you data, and then the user is blocked until then, and then they see data coming in. And imagine if you have five or six API calls, you just have different parts of the screen loading in different speeds, or you have to take care of issues like that.
Tanmai: And these are things that you'd already figured out when you build the app. But then when you did the API integration, it wasn't fun, and this is not a new problem. This is a fairly old problem. And so what people started doing was they said, "We'll have something like a BFF, like a backend for front end, and we'll aggregate this API." We'll provide one API, where you can fetch all the other five resources that you wanted and show that on your screen. This was becoming a background. Meanwhile, simultaneously on the Facebook side, they said, "You know what? What if we create, and what if we think about all these problems that front end developers face, and we solve this problem more systematically?" So what they did was they said, "Instead of making a bunch of API calls, why don't we all have a single API endpoint? Let's give this endpoint to the front end developer team."
Tanmai: And what that dev team can do is say, "I can make an API call and instead of specifying the resource that I want as a part of the URL", so instead of saying something like, I want to get a /user or /user/address, instead of saying something like that, you can now say, /GraphQL and what you submit to this endpoint is a query. So you make a POST request, where you submit a query, and you say, "I query for user and within user I want ID comma name, and I want address and within address, which is a nested node inside the user object, I want address.id, address.street, address.city, address.country."
Tanmai: And you can specify exactly the shape of the resource that you want and the GraphQL server then figures out that, okay, you need to fetch three or four different resources. So let's make this API call, and let's touch all these resources, and let's send these resources to the front end. So from the front end developer's point of view, now it's a great experience, because now I can make one API call, I can specify in that API my query, and I can get exactly the data that I want. And so, this is a huge benefit for the front end developer.
Owen: What you're saying is GraphQL allow me to have one endpoint that can query all the domain logic that I wanted to query.
Tanmai: Exactly, exactly. And it's very similar to imagine that, maybe if you're building a web API, as a developer you have something like SQL, or a query language, Mongo or something like that. You have SQL and using SQL, you can query everything in the database. You can query anything in the database that you want. And SQL is great for doing that. But imagine if the database gives you like REST end points, it would be so irritating for the backend developer, because every time you want to fetch something interesting, you want to maybe do a JOIN, you want to do some filtering.
Tanmai: It's so inconvenient because you want to fetch, you want to make a better query for fetching the entire "graph" or relationship structure that you want. GraphQL is very analogous to that power. It gives the front end developer that kind of power, that kind of flexibility in saying, here are the domain resources and here's my query for fetching the precise slice of domain resources that I want. And that power is so amazing for front end developers because now they don't have to wait for backend developers to create new endpoints. They can always query for exactly what they want as long as somehow the domain models are represented on the backend. It's a great experience for front end developers.
Owen: So how would I get started creating a GraphQL application? Do I define some sort of schema to open up my API endpoint, or how would I get started?
Tanmai: It's very similar to how you would get started with building just a normal API in a client-server web application. So on the front end, you're building your app, you start making API calls and you use something like a REST client or you use some kind of HTTP client. So on the front end, you build your front end, but instead of using an HTTP client, you use a GraphQL client. And a GraphQL client is basically a simple wrapper on top of an HTTP client, which allows you to conveniently create queries. And then you don't have to put in the exact URL in the parameters. You just write out your GraphQL query and you'll get the data, and then you can start using that data in your application. And on the backend, very similar to how you would build a REST server or maybe just an API server. The typical pattern is that you create something like a route site or a URL site, and so you specify the different URL bots and the different resources that you want to make available.
Tanmai: So maybe you say, I have a GET endpoint for the user, you have a GET endpoint for user address, you have a POST endpoint for creating a user, and stuff like that. And then in the REST API world, you would have mapped these URLs to functions, and these functions or controllers would have actually executed some kind of data fetching logic, or some security and authorization logic, and then return that data or return that JSON. In the GraphQL world, it's very similar, but instead of mapping URLs to functions, what you do is you map, you create GraphQL types. So you say, I have a user type, and I have let's say an address type and every user has an address. And so what you do is you say, "This is a user type. I'm going to have an address field inside the user type, which is a reference to the address type."
Tanmai: So you create these two types that are linked to each other. And then for each of these kinds of types or fields, you attach a function. So you say that if somebody requests for the user, like field or the user type, then this function can execute the logic for fetching the exact data for user. And similarly for address, you specify a function, and you say, this function knows how to fetch the address information. So now if the front end application makes a query and says, I want user ID1, name and address, and for address I want to address.city.
Tanmai: So what happens is your server will execute the function for user, execute the function for address. It will run these two functions, and then get the data, put it into a JSON structure, and then respond to the client. So very similar to what you would have done, with no magic. It's just that instead of having something that can process a URL and map it to a function, you instead process a query and map it to a function. These functions are called resolvers. So you map fields to resolvers like you map URLs to controllers, very similar.
Owen: So what would be cases that GraphQL would not be the good fit?
Tanmai: So a GraphQL API, from the description like I was giving you, it seems it's quite clear that if you have, you can model your domain objects to the schema and then every time I make a request you return some JSON data. That itself will point out those conditions where you realize that GraphQL is not a good fit. For example, if you have binary data. Let's say for example, I make a request and I say, "I want to fetch an image or I want to fetch a video or I need to fetch a stream of some data." In those cases, GraphQL is not ideal.
Tanmai: Or even if the response is not JSON, well that's a pretty clear fit for not being a great fit for GraphQL. But even if you have things like streaming, or you have binary data, that's not a good fit for GraphQL as well. And sometimes depending on the application that you have, you might realize that the way that you're modeling, the way that your API models are built, it doesn't really fit with GraphQL or maybe it's very chatty. Maybe the client and the server are very chatty. Maybe it's an internal application, it's very chatty, and it's not a great fit for GraphQL. But in most applications that we think about in the web and mobile landscape, GraphQL actually ends up being a really good fit.
Owen: So now let's change a little bit the topic to the adoption of GraphQL. What is driving GraphQL adoption today?
Tanmai: GraphQL makes the front end and the app dev team, it gives them superpowers. It makes them very productive. So in all of the cases where the end user application and the quality of the end user application, and the agility of being able to add, remove, and iterate on features of the end user application is important, GraphQL becomes very useful. So wherever we noticed that the business drivers are closely correlated to the quality of the end user application GraphQL starts sneaking in and the front end team says, "You know what, if you want us to be productive, give us a GraphQL API." And that's the primary vector. And that also answers situations where GraphQL is not the primary vector.
Tanmai: So that's kind of the primary reason, and what we notice in the world today is that so much of the way that we use technology, and the way people are using technology has shifted to being able to provide a good user experience on an application. And so many things for any business, whether it's a consumer, like a startup or a large technology giant, or whether it's an enterprise, even if it's a small store, so much of the way that they deliver technology to their end users is shifting to the front end. And the power of the application, the front end, that GraphQL is becoming important. And I think those two factors combined are causing a massive amount of GraphQL buzz in the front end ecosystem.
Owen: Now let's change the topic a little bit to the best practices of using GraphQL. What are some of the best practices in your opinion for using GraphQL?
Tanmai: I think it depends a lot on the existing situation that you have. Maybe, let's say for example, you have a monolithic application or let's say you have microservices, let's say you don't have front end applications, and you have mostly service to service communication, and actually you have different scenarios. Let's say you're building a new application or let's say you're adding GraphQL to an existing application. And so in all of those scenarios, the different things or the best practices of using GraphQL vary.
Tanmai: And if I can break down these individual scenarios one by one, if you have an existing monolith and you want to use GraphQL, there is good tooling today. So what you would do is you would use a GraphQL kind of, I won't say framework, but you would use something like a GraphQL module or a GraphQL library and this GraphQL library will allow you to create a GraphQL schema and map those GraphQL schemas to resolvers and these resolvers that you implement will talk to the underlined controllers that you have within the monolith. And in this case what you do is you have the ability to design a GraphQL schema that is similar to your REST models, but that also reflects the requirements of what the front end developers want.
Tanmai: And so you can design that GraphQL schema and then you can build that out and then you can map that. Now, depending on the framework that you're using, there are different approaches for doing this. One of the common approaches today is to have a GraphQL schema and then build manually a GraphQL schema, which is a different language. So it's a different language altogether. You have a file and inside that you write the GraphQL schema that becomes the URLs that are outside. That's one approach. The other approach is if you are, for example, you have a Java API, or some kind of typed language. Let's say you have Java or I think now maybe TypeScript, these languages you are already modeling the resources. And in these cases very often like for example it's Springboard, you might not even be explicitly creating REST API endpoints, you might just be creating models and the REST API endpoints are almost auto-generated. And in these cases, actually what you can do is you can just build your models and these models will generate the GraphQL schema and the GraphQL API automatically for you.
Tanmai: In this case, basically your GraphQL schema reflects the models that you have and that ends up working as well. So this is like the different ways that you have on the monolithic side. When you have microservices, GraphQL becomes very painful to use. And this is actually a point of stress for the community at the moment, which is, how do we deal with GraphQL and microservices? I feel there are many different approaches that have emerged. A very common approach is the GraphQL gateway approach, which is very similar to the backend for front end approach. So the BFF approach. So what you do is you say, "I'm going to build this." You take out a small team, like a team of two or three people, or maybe the front end developers decide to put together this team and this team now builds a GraphQL server, and this GraphQL server provides the GraphQL schema and GraphQL API for the front end developers or for the different applications that are being used.
Tanmai: And on the back it queries these different microservices that you already have. I think the best practice for using GraphQL is what would give you what really works for you. And I think it's very similar again to the early days of REST where you have a lot of REST best practices and the way you should use REST verbs, and the way you should do REST not modular resources, but once REST became an API that was used everywhere, people started crafting the REST API to be more suitable to what they wanted to do, and what their application was doing, and it automatically went through changes. So there was a lot of convention that emerged around different kinds of domains and how to use the REST API properly and what to do with the REST API, and we are going to go through that journey with GraphQL as well, where we'll see many different kinds of use cases and best practices and patterns emerge around those use cases for how you can use GraphQL.
Owen: So you have built a company to have the team to use GraphQL for a cloud native application. Have you seen any interesting usage of GraphQL?
Tanmai: It's been a fascinating journey for us. We're an open source engine. We launched just about a year ago and it's a GraphQL engine that works with the Postgres database, and we've now added the capability of it to be able to talk to other microservices, so that you can connect different microservices together and create a unified GraphQL endpoint, and our GraphQL engine takes care of being able to join across these services or join across what I call mid-tier services and databases, and provide an authorization kind of system so that you can expose right parts of the GraphQL schema to the right end users. Sometimes you don't want to expose the whole GraphQL schema, and you are able to enforce certain authorization policies. There is another transformation that is happening in the world today, which is the whole cloud native transformation, movement from containers to making containers stateless and to even serverless functions, which is like the extreme of a microservice. That is an entire movement that is happening in one part of the industry. The backend developers are moving towards being event-driven, of being decoupled, having services, having microservices, having serverless functions of using multiple SaaS APIs, they use vendor products, they use an API created by another team.
Tanmai: That is kind of one entire industry movement, that is happening powered by Docker and Kubernetes and all of the cloud native innovation that is happening. And on the other end, there's the front end team and the front end team wants GraphQL, and GraphQL works really well with the monolith, but it does not work really well with microservices or serverless functions or whatever. And so there's been a tremendous amount of interest in trying to figure out, how we can make both of those landscapes work well together. A nice way to connect a GraphQL API to various serverless functions and microservices is not hard, but to actually make that work at scale, to deal with performance, to deal with caching, to deal with security, it requires a new form of thinking for the organization to actually make GraphQL work really well with a "cloud native" backend.
Tanmai: And by cloud native, I mean, things that are microservices and serverless functions, and that are event-driven, so that are stateless, and there's been a tremendous amount of interest in trying to make that work together. Sort of the short answer is yes, there's a huge amount of interest in trying to make sure that we can get the best out of GraphQL for the application development team, and we can get the best out of our backend, and backend agility. And backend is a loose word. It can mean everything maybe on the infrastructure, and get a tremendous amount of developer agility on the backend as well.
Owen: Excellent. So you touched base a little bit of a GraphQL and microservices and talk about how your company is trying to solve this issue. I wonder though, what are the pains and learning between, well, using GraphQL for microservices?
Tanmai: You're right. I think, like I was mentioning a little bit before, a GraphQL API is powered by a GraphQL schema, and the GraphQL schema is essentially like a type system. And so if you've programmed in a typed language environment or statically typed environment, you notice that you create types, you build types or you build classes that provide functions, maybe you build types or maybe you're building classes and objects, and things like that. And then as you're building things, let's say you make an error in the name of a particular type, or the way you're referring to a particular type. So maybe the user type has an address field, and the address field is pointing to an address type, or a user class and then address class.
Tanmai: And let's say you make a spelling error inside the way you refer to the address class from the user class. When you build it, your compiler will tell you, "You know what? Here's a problem. There is no such thing as A-D-R-I-S." You spelled address, this thing does not exist. And so what you do as a developer is you're like, "Oh, okay, I need to go fix that." And actually you go fix it. Or maybe somebody else who's building a different module, they named their class user as well. And so now when they try to build it, they hit duplicate declaration. What's happening? And so then you as developers coordinate and you talk to each other, and you fix this problem.
Tanmai: But when you think about GraphQL with microservices, each microservice defines their own set of APIs. And when you try to bring them together with GraphQL, what you're trying to say is, "Hey, these are the various types of microservice one. These are the various resources by microservice two, and these are maybe the relationships between microservice one and two, between the types exposed by microservice one and two." Now, the problem is that if you think about the tooling of how these two microservices and types come together, this is very challenging, because the same problems that I talked about, like maybe you want to connect the user type to the address type.
Tanmai: How do you keep track of the fact that the type names are evolving or changing, or that there are errors in the references that you've created? So maybe when you dynamically build a graph, how do you know that it actually makes sense? There are actually services that are handling this. The problem moves out from the build time and moves into the run time. And that's just more challenging to deal with. And that's just maybe one example, but you can have all kinds of problems with overlapping types or you can have duplicate declarations and stuff like that.
Owen: Yeah. Thank you for sharing your experience with GraphQL and microservices. Currently, there's a working draft of the GraphQL spec. What's new? What's coming up next?
Tanmai: There are lots of discussions that are happening in the GraphQL spec, and the GraphQL draft around how to be able to namespace things or whether we should do it in GraphQL or not, or when you think about GraphQL mutations and input types of whether we want interfaces for input types or not. And so there's a lot of active discussion there but for the most part, the bulk of the GraphQL spec is very solid. A lot of the stuff that you need to do, that you need to build is all pretty much done. There are few nuances that I think are being worked out, and I think there's a lot of pressure from the GraphQL microservices side of things to move the GraphQL spec in a particular direction, but so far GraphQL is very solid and the spec is really solid.
Owen: Is there any topic that you would like to cover that was not covered today?
Tanmai: I would urge folks to go try out GraphQL and learn GraphQL. So that's really easy to do, at least to learn about GraphQL, whether you decide to use it or not. A tremendous amount, lots of resources to be able to quickly build an application with GraphQL on the front end or use a GraphQL API on the front end or build a small GraphQL server, just to get a flavor of what it takes. And I know, I mentioned a lot of challenges with GraphQL, but I absolutely love GraphQL and I think it's going to be amazing. It's important for us as a community to get hands on and experience the benefits of GraphQL, use a GraphQL API, integrate a GraphQL API, understand the nuances of GraphQL, and I think that will help the community evolve and figure out what the different kinds of things we can do with GraphQL are.
Owen: What is the best way to learn about GraphQL?
Tanmai: There are many different resources depending on what you're trying to do. I think, depending on the language or the framework that you're using. If you're a backend developer, there are several nice tutorials. If you just search for, there's something called Awesome GraphQL, which has a bunch of resources on the specific backend framework, and what kind of GraphQL library you can use, and they usually have some nice tutorials. On the front end side of things, there are lots of courses on Egghead that have a nice introduction to GraphQL or Udemy. We maintain an open source set of tutorials on learn.hasura.io, where you can take two hours to learn how to integrate GraphQL into your React app as a React developer.
Tanmai: So we have tutorials for React, Angular, Flutter, ReasonML, Elm, TypeScript and iOS, Android and React Native as well, all maintained by the community, and helps you get started with GraphQL super fast. The best way to find resources for GraphQL is usually to scope it in by the specific technology stack, that you want to be interested in. If you generally want to get a flavor for what the GraphQL API is, you can head to the graphql.org website, but from my personal experience, reading about GraphQL did not help me as much as when I used GraphQL to build a front end application, and that's when things started clicking for me. So I would encourage you to build something with GraphQL, especially on the front end to understand the power of GraphQL.
Owen: Thank you for joining us today, Tanmai. It has been a really useful conversation with you on GraphQL.
Tanmai: Thank you, Owen Ou for having me.
A podcast brought to you by the developer advocate team at Heroku, exploring code, technology, tools, tips, and the life of the developer.
← Previous episode
43. The GitHub Student Developer Pack
Next episode →
45. Illuminating Poetry with Technology
January 28th, 54. Building a Business by Teaching Developers
Lead Engineer, Heroku
Owen is a software engineer at Heroku and an internet plumber. In off time, you'll find him working on open source projects, or dunking basketballs.
More episodes from Code[ish]
Luca Maraschi and Julián Duque
When you're one of the largest telecommunications companies in Canada, you're responsible for building and maintaining services that can handle a volume of data many times greater than the average web server. Julián Duque had a chance to sit... →
Adam McCrea and Corey Martin
Heroku applications big and small run on dynos, virtualized Linux containers fine-tuned to execute your code. As the load on a server increases, you must add dynos to keep up with demand—but how do you know how many more to add? And how can... →
Ruben Bridgewater and Julián Duque
Errors are a fundamental part of the programming experience. Learning how to receive and react to them, as well as responding to the user who may have encountered one, is essential to building a great application experience. Ruben... →