When reading around comparisons between GraphQL and REST on the web, we are often told that we should use GraphQL because of this or that reason, or REST is still the way to go because of this or that problem with GraphQL. While these comparisons usually have a point, they often strive to find differences between the two types of APIs, attempting to convince the reader that one or the other API is better. But seldom do we find write-ups comparing how similar the two types of APIs are, pointing out how unimportant their differences may actually be.

To provide a different perspective, in this article I will pose several questions concerning differences between the two types of APIs, and provide an answer which suggests that the chasm between GraphQL and REST is, quite possibly, not be so big after all.

Can REST and GraphQL be always compared?

Both REST and GraphQL are APIs, i.e. mechanisms to fetch data from, and post data to, the server. In that sense, because they both serve the same purpose, they can always be compared. However, we must also be aware that while REST (which stands for "REpresentational State Transfer") is a concept, GraphQL (which stands for "Graph Query Language") encompasses a concept, a specification, and implementations by different vendors.

GraphQL being an implementation is important because different GraphQL servers, while needing to adhere to the GraphQL spec, can also deliver custom features of their own, which may enhance the functionality for a GraphQL API over a REST API. However, that's not GraphQL vs REST anymore, but a specific GraphQL server vs REST.

For instance, the @defer and @stream directives make the API provide an initial faster response, by splitting the data into different chunks that are returned at different times. These directives are not yet part of the GraphQL spec, and only a handful of GraphQL servers currently support them.

Are REST and GraphQL fundamentally different?

The most important reason in how GraphQL differs from REST is that in GraphQL the requested data must be specified on the query itself, instead of being pre-defined in a fixed endpoint as in REST. For instance, to obtain data for posts in REST, we may create an endpoint /rest/posts/, which will always return the same set of data fields. If later on we need different fields, we will need to create a new endpoint /rest/posts-2/.

In GraphQL, the needed fields are specified on the query, like this:

{
  posts {
    id
    date
    url
    title
    content
    comments {
      id
      date
      content
      author {
        id
        url
        name
      }
    }
  }
}

If we need different fields, we just update the query accordingly (on the client-side), without any change to the endpoints (on the server-side). As we can appreciate, the difference between GraphQL and REST is not otherworldly. If your goal is to fetch data to power your application, well, you can do it with either type of API. Their main difference is simply how the data fetching is accomplished.

As a result, you will most likely be able to use either GraphQL or REST and decide which one to use based on your preferences, or how suitable it is for your project.

Are REST and GraphQL equally approachable?

For developers just starting out using APIs, REST and GraphQL are equally approachable, and anyone should be able to master these APIs with the same effort. That's because the GraphQL syntax and the usage of REST verbs (as examples of some characteristic from each of these two APIs) may be different, but neither of them is more difficult to learn than the other.

There are people emphasizing that GraphQL has the extra disadvantage of having to learn its syntax. But those are developers who are using REST, and also had to master REST verbs back when they started learning REST. If they could do it then for REST, I'm sure they can do it now also for GraphQL.

In summary, switching from REST to GraphQL should not be difficult at all.

For non-developers, GraphQL has some advantages and disadvantages that may make it easier or harder (depending on who you ask) to start working than REST. GraphQL has an extensive availability of open source clients, such as GraphiQL and GraphQL Voyager (both reviewed in article Learning with screenshots: GraphiQL and GraphQL Voyager), which make it a easier to visualize and comprehend the GraphQL schema, and interact with the GraphQL service. This is one of GraphQL's greatest strengths.

However, paradoxically, this is one of GraphQL's weak points, because these clients feel like a must. If we don't have them, we may feel handicapped when interacting with the GraphQL API. And at the very beginning, when non-techies are starting to learn how to use the API service, this may prove to be a roadblock.

A REST endpoint, on the contrary, could be simply accessed by pasting the endpoint's URL in the browser, after which we can evaluate its response. As such, we can more easily understand what an API is and how it works, using the same tool we use every day to browse the web.

In summary, there's no definitive advantage of one API over the other. Given the right motivation, anybody can learn to use either of them.

Is coding for GraphQL more difficult than for REST?

Browsing websites and documentation gives the impression that GraphQL requires a bigger effort to set-up than REST. Depending on your use case for GraphQL, that could be the case or not.

For instance, sites such as graphql.org (the official GraphQL site) and howtographql.com (a site providing tutorials to learn GraphQL) explain in detail what field resolvers are, how they work, and how to code them. When browsing these sites for the very first time, we could feel it is too much information and all together too daunting just to start coding for GraphQL.

However, coding a field resolver for GraphQL is not really that different from coding a route handler in REST. They are both functions that, given some parameter, produce some response. Calling them "field resolvers" or "route handlers" is a technicality; their essence is the same. In that respect, GraphQL is not more difficult than REST. Moreover, new GraphQL frameworks and services may abstract the logic for creating the GraphQL schema, making it very simple to create field resolvers. (For instance, check out StepZen's @rest directive.)

Now, when hosting your own GraphQL service, you must implement additional measures, requiring some extra effort. This is due to the undefined nature of the query, where we must make sure it always works, that the schema doesn't leak private data, and that the service can repel malicious attacks, among other challenges.

For instance, we must be aware of the N+1 problem, which could make the reponse take a long time, degrading our API service. Depending on the GraphQL server, a solution for the N+1 problem may be automatically provided by the server itself, or may depend on code provided by the developer, thus increasing their effort.

Similarly, with GraphQL we are exposed to a new kind of attack, such as the execution of deeply nested queries, which could fetch a huge number of records from the DB, making it crash. To account for it, the developer may need to implement a query cost analysis strategy, which translates into a bigger effort. The fact that GraphQL does not restrict what data can be requested in a query is both a powerful capability and a potential danger. As the saying goes, "With great power comes great responsibility."

Coding for REST is simpler because the data returned by its endpoints is pre-determined, so we can have the absolute control on how the API is used. No surprises, but also no gains.

If we already have REST in the application, do we still need GraphQL?

When creating an API from scratch, my own preference is to use GraphQL (unless the API is so simple, that GraphQL doesn't provide any advantage over REST.) But if you already having a REST API in the application, would adding a GraphQL API make sense?

As always, it depends. If whatever data requirement by the application can be easily satisfied via REST, then I believe there's no need, and having to maintain two APIs may not be worth the trouble. However, if the application could benefit from some feature that is natively implemented by GraphQL, then I believe that the answer is yes. In that scenario, we can decide whether to use REST or GraphQL, on a feature-by-feature basis within the application.

For instance, with GraphQL we can avoid over-fetching data. REST endpoints can also allow you to restrict which fields are served, but the results will not be as good as with GraphQL, and they will require extra effort to implement.

For instance, the WordPress REST API offers the /wp-json/wp/v2/posts/ endpoint to fetch posts:

[
  {
    "id": 1657,
    "date": "2020-12-21T08:24:18",
    "date_gmt": "2020-12-21T08:24:18",
    "guid": {
      "rendered": "https:\/\/newapi.getpop.org\/?p=1657"
    },
    "modified": "2021-01-13T17:12:34",
    "modified_gmt": "2021-01-13T17:12:34",
    "slug": "a-tale-of-two-cities-teaser",
    "status": "publish",
    "type": "post",
    "link": "https:\/\/newapi.getpop.org\/uncategorized\/a-tale-of-two-cities-teaser\/",
    "title": {
      "rendered": "A tale of two cities – teaser"
    },
    "content": {
      "rendered": "\n<p>It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, ...<\/p>\n",
      "protected": false
    },
    "excerpt": {
      "rendered": "<p>It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, ... <a class=\"more-link\" href=\"https:\/\/newapi.getpop.org\/uncategorized\/a-tale-of-two-cities-teaser\/\">Continue reading <span class=\"screen-reader-text\">A tale of two cities &#8211; teaser<\/span><\/a><\/p>\n",
      "protected": false
    },
    "author": 1,
    "featured_media": 0,
    "comment_status": "closed",
    "ping_status": "closed",
    "sticky": false,
    "template": "",
    "format": "standard",
    "meta": [],
    "categories": [
      1
    ],
    "tags": [
      191
    ]
  }
]

We can restrict the returned fields via param ?_fields=..., such as doing ?_fields=id,title,excerpt, even nesting fields, such as doing ?_fields=id,title.rendered,excerpt.protected:

[
  {
    "id": 1657,
    "title": {
      "rendered": "A tale of two cities &#8211; teaser"
    },
    "excerpt": {
      "protected": false
    }
  }
]

However, the fields and nested fields must already be present on the endpoint's original response. For instance, there is no nested data for author on the endpoint /wp-json/wp/v2/posts/, only the author's ID. Hence, I can't do ?fields=author.name, and instead need to create another endpoint, just for this purpose.

Another example is batch operations. These have also been introduced in the WP REST API, so we can pass the following data to the /wp-json/wp/v2/media/<id>/edit REST endpoint:

{
  "modifiers": [
    {
      "type": "crop",
      "args": {
        "left"  : 0,
        "top"   : 0,
        "width" : 80,
        "height": 80
      }
    },
    {
      "type": "rotate",
      "args": {
        "angle": 90
      }
    }
  ]
}

In my opinion, it doesn't make a lot of sense to spend a lot of time and energy developing this for REST when a GraphQL API could handle it natively.

We could execute a batch with mutations cropImage and rotateImage without a big effort in GraphQL:

mutation EditImage($imageID: ID!) {
  # Crop the image
  cropImage(
    imageID: $imageID
    left: 0,
    top: 0,
    width: 80,
    height: 80
  ) {
    id
  }
  # Rotate the image
  rotateImage(
    imageID: $imageID
    angle: 90
  ) {
    id
  }
}

In summary, if the application already uses REST and could benefit from the features provided by GraphQL, then also introducing a GraphQL API may be worth it. But, as always, there's no pre-determined answer, and each project needs to be considered on its own.

Conclusion

GraphQL is a great improvement over REST. However, I consider it that, an improvement, and not a revolutionary new technology that requires a complete different mindset. Not at all. If you are comfortable using REST, you should also feel comfortable using GraphQL.

Now, if you are currently using REST, should you do the jump to GraphQL? As always, it depends. But should you consider it? Absolutely. You can either stay with REST and see no change, or possibly start using GraphQL because it will benefit your application. As always, the decision is yours.