Simply said: GraphQL
Dec 20, 2021
GraphQL has been around for a while, and it managed to establish its strong position in a developer's toolbox. Today, however, we will look at it from a less technical perspective.
In this piece, I will try to provide some context on why GraphQL is so loudly discussed, and more importantly, so widely used. The audience of this article is less technical than usual, and the reason for that is simple: to make the web more inclusive.
Web development is saturated with all these terms you hear being thrown more than average. While that happens to some of them for a good reason, the web is most definitely not indifferent to hype. This infectious excitement towards technology is what fuels us, the developers, and it sometimes can even sell a product ("Wow! This new tool uses blockchain, it must be legit!").
This article contains a glossary
If you see a word that looks like this, click on it to see its definition.
However, the reasons for the hype to surge, may not necessarily be clear for everyone. I feel like sometimes we - the developers - don't do enough to invite some other parties into our discussions, especially that software is not only a concern to people who write it but also to the ones who have to manage or sell it.
The "Simply said" series is an effort to try to balance that. So, here it is: GraphQL in a more accessible light.
Useful links:
1. What is an API?
Every commercial application is in control of some sustained data. If you registered your account, it doesn't matter if you try to log in the same day, or a month later, the data should be there thanks to a database it's stored in.
Database is the final destination of our data, and this entire process starts with retrieving it from the user (through an interface, like a registration form).
It is done through a fundamental web feature - a request. It is a communication attempt between any web entity and the server. A server is, in this context, a piece of software running on a computer, that supports the interchange of data with other devices, thereby providing them services.
So, the user fills the form, clicks "Submit", and the provided data gets sent to the database so that it can be retrieved in the future. For example on a page, where we display a "users" table:
A list of all the users is sensitive, and access to such should be restricted - for example, only to admins of the website. This scenario violates our current mental model of a free exchange of information between the application, and the database. We will correct it with an addition of a missing piece in our diagram:
The API - Application Programming Interface - is the missing piece. In our case (because what I am describing is called Web API), it's software we ask to perform certain actions that result in a database operation. We - from the level of our application - don't need to know the specifics of reaching our database, we don't communicate directly with it, we simply ask the API to do it for us. All we care about is the result of that action, which can be, for example, a list of users.
Here, it's worth noting that on our graphs each arrow towards the API is a request, and each arrow towards the application is a response to that request.
If we broaden this perspective, we can begin to notice that it's not only a programming thing. When you are driving a car, and want to accelerate, you push the gas pedal with your foot. It is not the motion of the gas pedal nor your foot that makes the car go faster, it simply communicates to the car's engine the desire to go faster.
Volvo manufacturers decided to limit the maximum speed of their cars to 180km/h (~112 miles/hour), which means that when you continue pushing the pedal after reaching the threshold, nothing happens. You communicate your desire of accelerating as usual, but the car responds negatively.
The same can happen when communicating with an API: you can request the list of all the users, but the API responds - "I will not give it to you unless you are an admin". Thus, the API is a "higher instance" that makes decisions on what actions to allow, what data to share, and so on.
2. The traditional (REST) way
So, let's sum up what we know. We have a client (an application, in our case) that wants to access some information from the database. There is a layer in between, that decides the scope of shared data, called API. Now, we will deepen the actual communication between the client and the API.
Over the years, under different use-cases and technological restrictions, we've seen the rise of a plethora of communication standards, such as SOAP or gRPC. However, the most commonly used way of communicating with a web API is called REST. It is an information exchange convention that assumes two major points:
- We use five verbs to express the intention of our request:
GET
,POST
,PATCH
,DELETE
,PUT
. They come from the HTTP request methods, but it's not super important. Their meaning can be mapped to:
GET
-> "please, give me that resource" (like a list of users)POST
-> "please, add that resource" (adding a user to the list of users)PATCH
orPUT
-> "please, update that resource" (changing a user's name)DELETE
-> "please, remove that resource" (delete a user)
- We use the name of the resource in the request to specify what data we want to retrieve.
Let's say our API can be found under the URL: https://www.peelar.dev/api
. If we would want to retrieve all the users from this API, the address for that request may look something like that: https://www.peelar.dev/api/users
, and for all the posts: https://www.peelar.dev/api/posts
.
These restrictions were set to establish a standard, that can be distributed and used. Without these standards, if we would allow all the APIs in the world to communicate as they like, there would be chaos. Imagine all the people in the world talking in their own, made-up languages.
Let's use what we learned, and put it on our graph:
While REST had been (and for a lot of people, still is) the golden standard of client <-> API communication, it has its limitations.
Let's imagine you are a detective 🕵️ trying to crack a difficult case.
To do so, you have to analyze some information that is stored in the police department's warehouse.
You go down the stairs and approach the desk behind which there is a police worker named Greg that issues the requested documents. All you need for your analysis is the date of the conviction, first name, and last name of the convict in all the parking violation cases of the last 10 years.
If Greg was a REST API, it's possible he would respond: "Sorry mate, we don't have our data cataloged this way. The best I can do is give you the list of all the crimes ever, and each case will consist of the name of the detective that lead the case, the first name and last name of the convict, as well as his second name, birth date, where he went to school, and a bunch of other completely unrelated information."
3. The GraphQL way
If Greg was a GraphQL API, he would respond: "No problem, there you go".
That's because with GraphQL, the client determines the shape of retrieved data. Of course, the API can still choose not to send it (because, f.e., the user doesn't have access to it), but the change is substantial. With REST API, if the API decides to respond with data you will not necessarily need, along with the data you asked for, there is nothing you can do about it.
One extra column when asking for a user is nothing we should worry about, but if the REST API was not designed properly sending back excessive data can cause some serious performance issues.
If all we want to display is the text "Hello, {username} 👋", but the username is stored inside an object that also contains the user's entire biography, we keep the user waiting for no benefit.
Each excessive piece of information costs precious kilobytes, that take time to download. GraphQL drastically reduces the overload of data, allowing us to request the exact data we need.
GraphQL offers a special language to communicate with its APIs, that allows you to point which exact resource you want to retrieve. Trying to fetch the first name and the email of all the users would look like this:
query {users {firstName}}
Sending a request with that query could result in the API responding with:
[{"firstName": "Adrian","email": "admin@peelar.dev"},{"firstName": "Keyser","email": "keyser.soze@gmail.com"}]
We know there are other fields in our database, like the lastName
, but because we didn't ask for it, the GraphQL API didn't send it.
The features of GraphQL don't end here, though. One of the biggest advantages this technology gives you is the types. Every resource returned from a GraphQL API has to be described beforehand, so when you are fetching it, you know exactly what is it.
Let's analyze what's happening in this graph:
The client (our application that contains the table) sends a request for all the first names and emails of all the users.
The API has (and shares it with us) a definition of what a "User" is:
type User {id: String!firstName: String!lastName: String!email: String!age: Number}
It contains five fields: id
, firstName
, lastName
, email
, and age
, out of which the first four are text fields ("Strings"), and the last one is a number. The "!" symbolizes whether the field is required or not, but that's not important here.
Thanks to that definition, we know what the user will look like even before successfully fetching it. We know that all of the fields we asked for (
firstName
andemail
) are text fields, so we can treat them as text fields (we can, f.e., uppercase them which would not be possible with a number).The API responds with the list of the users, out of which the first one is named "Keyser".
These two features are one of the biggest GraphQL strengths. When we ask for a specific resource, we get just that, and we don't have to guess what will it look like when it arrives. No wonder that GraphQL has found its way into complex codebases, as it can improve both performance and error-proneness of our application.
It's not like the API world ends at GraphQL, though. Some of its highlight features were implemented in a bunch of REST API variations, making it more rigid and dependable. GraphQL also has its drawbacks, that are however being dealt with the more recognition this solution gets (which is already quite high).
I hope I managed to outline the context of the browser <-> server communication, as well as the differences between REST and GraphQL API. If you enjoyed this article and would like to see another web-related term explained in such a way, hit me up on Twitter!
You are not going to believe those 😱: