Why GraphQL When REST Is A Tried And Tested Solution?

Post Images

I started a course about GraphQL and React on Udemy. The start of the course is at least interesting so I decided to write about it.

Why GraphQL?

The course starts with the concept called RESTful routing which is all about standardizing the URLs used to manipulate resources. Basically something like:

/<name> POST create a new record

/<name> GET fetch all records

/<name>/:id GET fetch record with given id

/<name>/:id PUT update record with given id

/<name>/:id DELETE delete record with given id

If you ever played with REST you already know this, nothing new so far.

Things get complicated with RESTful routing when we add relations. For example:

/<parentResource>/:parentResourceId/<childResource> POST create a child resource associated with its parent resource

...

/<parentResource>/:parentResourceId/<childResource>/:childResourceId DELETE delete child resource with childResourceId created by parent resource with parentResourceId

Now imagine nesting data a couple more times. Something like /root/:rootId/parent/:parentId/child/:childId/childChild/:childChildId... and so on.

The course continues with a somewhat complex example:

Users each with an image, name, company name and position name. And such relations can be stored in three tables: users joined with companies and positions.

The problem occurs when we want an user related with other users (his friends) which each have companies and positions. The instructor suggests the following:

One request for the user: /users/:userId GET, another request for its friends /users/:userId/friends and next... one request for each company and each position. Basically

/users/:friendId1/companies GET

/users/:friendId1/positions GET.

The problem with this approach is obviously too many HTTP requests, so unacceptable degradation of performance.

Another approach for the last part would be:

/users/:userId/friends/companies GET

/users/:userId/friends/positions GET

This approach looks better as it adds only 2 extra requests.

And the instructor suggests the third approach which breaks REST rules:

/users/:userId/friends-with-companies GET (this is one custom endpoint to get all data).

Now my two cents about this.

In practice working with complex REST APIs I noticed two ways of dealing with this nested relations issue. The first is the one above which is the obvious choice if you want your API to be performant.

The next choice is a little bit complicated and involves parametrizing the endpoint. For example:

/users/:userId/?relations[]=childRelation1&relations[]=childRelation2&relations[]=childRelation3

This approach has its own problems: what if I don't want all columns of relation #2 (childRelation2)? Well... in such a scenario... parametrize even more. Of course doing what you just saw above is absolute madness and I don't recommend it at all. This was the worst designed API I ever worked with and I basically refused to learn it in order to not make myself dumb.

The project using the API above started having performance issues with a few dozen users... I'm gonna stop now with the critique... never do this!

Going back to the course, the logical approach /users/:userId/friends-with-companies GET has the issue of returning data we may not need (over-fetching as it is called). For example returning the entire company model for each friend when we may need just the company name. Of course we can parametrize... thus adding complexity and creating spaghetti code if we don't know exactly what we are doing. Are you following this? Can you imagine the amount of complexity in the code for just a couple of nested relations?

So please welcome GraphQL - the solution to the performance issues above. GraphQL solves both too many HTTP requests and over-fetching data problems simultaneously. Because with GraphQL we can perform a single HTTP request to return a graph with all needed data (a graph is a data structure that contains nodes and relations between nodes).

The interesting part is that GraphQL is a query language... so GraphQL is not concerned about how we store our data. We can have the same database model exposed via REST and GraphQL endpoints simultaneously. Actually PHP software like API Platform already does this just by installing an extra bundle for GraphQL and adding some configuration - no changes to the data model whatsoever!

Let's rewrite the nested relations endpoint above (/users/:userId/friends-with-companies GET ) using GraphQL syntax:

query {

user(id: "13") {

friends {

company {

name

}

}

}

}

Can you see the power of this? And as you can imagine: the query above will return all the data we need.

I stopped the course here because I am tired. I don't know if I will write more about this course, I'll see.

I really hope you noticed the limitations of REST and the power of its successor: GraphQL. There is a reason the most complex web application there is (Facebook) uses GraphQL. And React while we're on the topic.

And once again, this is the link to the course. Amazing work!

AndrewStarlike

I'm a web programmer passionate about coding, spirituality, psychology and some theoretical sciences. The best part with so many interests is I never get bored.

Instagram Posts