David Hockley

GraphQL vs REST

It's time to explore together the wonderful world of GraphQL and REST!

Let's take a look at what GraphQL is, what REST is, and when you should choose one over the other. What is the need they exist to serve? What are they used for? Why and how to use them? So many questions!

And we'll see the four advantages that GraphQL has over the REST-ful style of APIs.

And then the 2 major disadvantages that you have to watch out for if you use or create an API in GraphQL.

But before that, let's start at the beginning:

What is GraphQL?

GraphQL is a way to create web APIs. I've already written about APIs in general, and REST web APIs in particular(https://medium.com/gitconnected/what-is-a-rest-api-6471b08eb575).

And while the REST standard is the standard way to organize an API, GraphQL is steadily challenging that position of dominance. To understand GraphQL, and the purpose it serves, we will be comparing it with how REST APIs are organized.

I hope you like the end result…

And truth be told, you could almost say that GraphQL exists because of "likes". GraphQL was born over at Facebook. And it was built to meet a need specific to social networks. A problem that the "like button" itself embodies.

Because GraphQL's main purpose is to navigate a relational network.

1. GraphQL is better for relational data

What do I mean by that? Well, REST is particularly suited to the classic table-based database setup, where each row represents an object. After all, REST stands for Representational State Transfer.

To simplify, the purpose of REST is to communicate an item or several items of a collection or table in a database. In REST terms, these are respectively called "resources" and "resource collections". We request that the server provide us with the data of a given book, or a collection of books, for example.

But social networks are about relationships between different types of items. Who are my friends' friends? What content do they like? What do they watch? What type of content do they respond to?

Conceptually friendships, follows, and likes are links. They're relationships between things.

These links, combined together, form a graph, where nodes (users, pages) are linked together (via likes, follows, views & visits…).

GraphQL provides the means to create queries that traverse this graph, across different kinds of objects. Unlike REST where one request will usually only get you one "type" of item.

And therein lies the meaning of the name GraphQL, which stands for "Graph Query Language".

Unlike REST, GraphQL truly is a query language, as is for example the Structured Query Language (also known as SQL).

In REST the entry point (the URL called and the HTTP verb used) determines the server's response is determined. In GraphQL you only talk to one entry point. How?

We send an HTTP request that contains a page of text written in GraphQL that describes our query.

These requests are mainly of 2 types. You can send a read request, known as "Query", or a write request, known as a "Mutation".

Now, I'm a big fan of learning by doing, and we'll be using the Star Wars GraphQL API, you can follow along if you like(https://github.com/apollographql/starwars-server). All you need to do is a git clone a yarn install and yarn dev!

Now, let's try out a simple query. In the read query, we list all the fields we want to have in return. For example, in the StarWars API just installed above, we can do:

query {
  hero {
    id
    name
  }
}

We're requesting the date for the main hero, specifically his id and his name. And as everyone knows, the film's main hero is… R2-D2, obviously

2. GraphQL allows client-side date shaping

Here we see GraphQL's second advantage: the client defines the shape it wants the data to take. What's the point of that?

For mobile users in particular, but on the web in general, the quantity of data to be transported has a cost, measured in time, bandwidth, and interactivity. Now let's take this a little further.

As I mentioned earlier, we can browse the links of the relational graph in the same query. Here in this example, we can retrieve the hero's friends, once again specifying the fields we want to have in return:

query { 
  hero {
    id
    name
    friends { 
      id
      name
    }
  }
}

Here we get the hero's friends, with their id and name.

When I type the code in the editor (the GraphQL playground), it gives me suggestions. What's more, the playground provides documentation. The reason this is possible is because of introspection, which is GraphQL's third advantage.

3. GraphQL is self-documenting

What is introspection? GraphQL has a special feature built-in (and built on the frustration of dealing with REST). It has built-in queries which allow you to document, through GraphQL itself, what fields and queries are possible.

The playground runs those queries to be able to show its suggestions. So for example, if I send the following query

query { 
  __schema {
    queryType {
      fields {
        name
        type { 
          kind 
          name
        }
      }
    }
  }
}

This query returns a list of possible queries on the root node. Including the hero request seen above.

And this feature is a response to one of REST's biggest flaws: you need external documentation to use it. External documentation is error-prone, incomplete, and out of date.

There have been attempts to create self-documenting formats in REST. None of them have taken hold, because there is no standardized implementation. REST is a guideline. In GraphQL self-documentation is part of the specification, and comes baked into the protocol.

Now let's talk about types.

4. GraphQL is a typed language

If we go back to the previous query, we see that the introspective documentation as well as the documentation tab presents the return values.

In GraphQL things have a type. And strong typing is GraphQ's fourth advantage.

Now, what are the different types in our API? How do the types work?

Well, this strong typing combines well with the introspection of GraphQL, which will be able to answer us.

If we run the following query:

query { 
  __schema {
    types { 
      kind
      name
    }
  }
}

We see several fields of type Scalar. These are the basic types. There are 5 of them:

  • String,
  • Boolean
  • Int (integers),
  • Float (floats)
  • and ID (which can be a string or an integer)

If you go through GraphQL documentation, you'll also see two more notations: exclamation marks and square brackets.

The square brackets mean what is returned is a list or array.

The exclamation mark means that the thing returned cannot be null

And then we also see specific types like (in the case of the Star Wars API) Human or Droid and again we can use introspection to see the type of these more complex objects.

This allows us to see at the same time how we can pass parameters in queries.

So, if we are looking for the type that has the name Human, we query the fields of the object and get the types.

query {
  __type(name: "Human") {
    fields { 
      name 
      description 
      type {
        kind
        name
        ofType { 
          name 
        }
      }
    }
  }
}

We can see that we can retrieve object types directly from the GraphQL API. GraphQL's strong typing, therefore, works particularly well with TypeScript and typed languages in general (like Flutter).

So we have seen 4 major advantages GraphQL has over the RESTfull style:

  • relational graph querying,
  • introspection,
  • typing,
  • and client-side data-shaping

But not everything is rosy. GraphQL's strengths of GraphQL also have weaknesses.

The trouble with GraphQL

The fact that the client defines the shape of data makes caching the query (and optimisation) more difficult.

But the second flaw is even more cumbersome. This is called the N+1 problem, and it is due to letting the client decide how heavy the query is.

The client can, if it so wishes (and if the server does not have any additional configuration), run absolutely all the queries in a single request.

In itself, not great but not necessarily dramatic, the complexity remains fairly linear.

The real problem is that by searching for the children of the children, you can end up with a complexity that grows exponentially.

By default, there is nothing to prevent me, in GraphQL, from looking for the friends of my friend's friends, and so on. Nothing, except that I risk bringing the database down to its knees.

It then becomes the responsibility of the front-end developer, to ensure the database is not overloaded.

And that's potentially a terrifying prospect.

Key Takeways

Thankfully, some implementations can block this level of nesting, and GraphQL's advantages — notably typing and self-documentation through inspection — result in a far superior developer experience.

And that smoother, more fluid experience makes GraphQL more fun.

And if you're a regular here, you know that I'm passionate about understanding what makes code fun.

And if you're not yet a regular but you've made it this far, this is your chance to create one of those links that graphs are made of by clapping for this article or even, dare I ask, following me for more code-related content!

In any case, see you soon!

Social
Made by kodaps · All rights reserved.
© 2023