GraphQL: the REST is history?

A little intro to what graphQL can solve

Stav Barak
Israeli Tech Radar
6 min readJan 13, 2020

--

Doodle courtesy of a friend, as are all the sketches and charts in this post.

GraphQL Is Really Buzzing Right Now.

What’s that all about?

GraphQL, created by Facebook in 2012, first stormed into our lives in 2015 when it was open-sourced by them. It is said to revolutionize the way we think about APIs. Before we dive into what that big statement means exactly, I need to say: GraphQL was made to solve a rather specific set of problems, or if you will, the shortcomings of the REST approach. In order to understand if it’s the right approach for us, we need to understand what those shortcomings are.

RESTful Routing Is Fine

REST APIs have become pretty much the standard over the years, and for good reasons, too. RESTful routing makes it really easy to communicate with someone else’s API without any special effects or third-party libraries, providing a way of mapping between HTTP verbs (get, post, put, delete) and controller CRUD actions (create, read, update, delete).

In simpler words, it’s just a set of conventions used to fetch or manipulate data from the server. When we talk about RESTful routing, we really talk about HTTP requests; what types of requests we need to create, read, edit or delete a record. This set of conventions tells us what the API looks like so that we know what resource to expect from the server when we go to a certain URL.

REST APIs inform the client about the result of their request using status codes, and additional information in the body of the request.

So far so good.

But REST Has Its Flaws.

And I’m going to elaborate a bit about some of the major ones.

Multiple Requests

Typically, we would need to access several server-defined endpoints, and we might need to do multiple round trips to get everything we need. For example, in an app that has users and blog posts, to get a specific post made by a specific user we would send a GET request to URL /users/{userid}/posts/{postid}. Now if we want to know something else about the user at the same time, like their birthdate or workplace, we have to make another request to /users/{userid} to get the user entity.

That’s two requests. Can we get it for one?

Server Driven Representation

Say we have a Linkedin type social network. The data consists of users, and for each user, we have their info, their connections (other users), workplaces and positions.

When we design the data store here, we need to remember that each company is also an entity we want to access, and it has its basic info and a list of users who work there. The positions should also be entities of their own so that we can pull a user out from the collection of positions, same as with the companies. The user can have a key that points to a certain company and position that they’re associated with.

Take a couple of minutes to think about how our REST API here is going to look if we want to be able to fetch the following:

  1. The list of users (/users) — ok, seems legit!
  2. A specific user (/users/{id}) — still good.
  3. A specific user’s list of connections (/users/{id}/connections) — sure.
  4. A list of the companies associated with all of a user’s connections — Oh. Wait.

The last one here is kinda tricky.

As far as RESTful conventions go, we can create a request for each user’s connection’s company: users/45/connections/1/company, /users/45/connections/2/company, etc. It’s obviously unrealistic to have that many HTTP requests.

Another option is to customize an endpoint like this: /users/45/connections/companies. So, in theory, we’ll get all the companies related to the specified user’s connections. However, if we‘re going to create tons of very customized endpoints like that, we’re going to have to actually make this thing work on the backend, and put together the queries to fetch those very particular pieces of data — so that’s hardly scalable in real life.

Or we can go about making even more customized single endpoints like users/45/connections-companies, and design those fixed data structures so we can return them.

That’s where the RESTful conventions really get thrown into the trash, which also brings us to the next issue:

Overfetching / Underfetching Data

For each company, we’re probably going to have to return the entire model — including name, id, location, year founded, and then again, an entire list of users associated with it… What if we actually just wanted to get a list of names? On the other hand, if we are using endpoints that return fixed data structures, they could be lacking other pieces of data and forcing the user to make additional requests.

This use case involves heavily nested relationships between pieces of data, and it seems that the RESTful conventions won’t make much sense here, because if we don’t want to make a ridiculous number of requests to the server, we would either be customizing many weird logic endpoints or be extremely overfetching data.

GraphQL to the Rescue

These are the challenges around RESTful routing and data serving that GraphQL is here to solve. The rest of this reading is going to be a brief showcase of what it can do.

Everything is Connected

GraphQL doesn’t deal with dedicated resources, but instead, treats the data as a graph.

With the GraphQL query language, we can query exactly what we need and describe exactly what attributes we want to get back in the response.

Here we can query something like this:

query {
user(id: "15") {
connections {
company {
name
}
}
}
}

In this example, we’re telling GraphQL to find the starting point user with the given ID, then go find all the users that are user 15’s connections, and then the company in each of these users, and have it return just its name. GraphQL will walk through all the records associated with the given starting point, all the way to the final result.

And we can get as specific as we want with a single query, like fetch all the CTOs among a certain user’s connections, or the companies’ locations for all the connections of a connection, or what have you. As long as the schema supports it — we can go wild. GraphQL helps us reduce network requests by allowing us to do so much in a single query, and no more overfetching or underfetching data, since we only fetch exactly what we need.

Error Handling

A GraphQL query can have many resolve functions, for whatever types you want to query in it. While in REST we’d get a response status code to know what the error is, GraphQL will not fail the entire query, but instead will always get a status code of 200 and send the error message along with the response to the client. If we’re querying this:

query {
user(id: "15"){
firstName
lastName
company {
name
}
}
}

For a user that is currently unemployed, we’d get back this:

{
"data": {
"user": {
"firstName": "Jonny",
"lastName": Rotten,
"company": null
}
},
"errors": [
{
"message": "Request failed with status code 404",
"locations": [
{
"line": 5,
"column": 5
}
],
"path": [
"user",
"company"
]
}
]
}

And see we still get other data, like the first and last name. Only the company is null. How cool is that?

To Wrap It Up

There’s much more to GraphQL than this very brief introduction and a lot more to REST too. GraphQL has a whole different approach regarding API design, and it solves many of the challenges we had to deal with using REST. It also has its own challenges (and that can be a new post).

Is one of these approaches better than the other? Like everything in technology, the answer to that is very rarely a confident yes. Each of them has its advantages and weaknesses, considered against your client's needs of the API. However, in the world of social networks, as shown in the examples above, in my opinion, GraphQL is a winner.

Hope this was helpful!

--

--