GraphQL: Is it really better than REST?
By: Usame Yilmaz
Tags: GraphQL, Service Design, Software Architecture, Software Development, Rest

Overview

Over the last years, REST has become the strongest and most popular option for designing web APIs. In most cases, REST does very well. It is easy, performs and scales very well. RESTful APIs do not require any special libraries, help the client and server to be loosely coupled and thus improve the efficiency of client development. However, as with any other technology, it has pros and cons.

GraphQL has been presented as a revolutionary alternative to REST. It was initially developed by Facebook to cope with the limitations of traditional REST APIs, such as overfetching and underfetching.

In this post, my aim is to build understanding of how REST API’s and GraphQL differ, what they have in common and when you might want to use which. I’ll dive deep into some sample implementations with comparisons as well.

Please note that, this article assumes basic knowledge of REST API’s and related concepts. If you’re not familiar with, it would also be useful to have a quick look at those concepts.

So, what is GraphQL?

GraphQL, as its name suggests, is a query language for APIs and a runtime for fulfilling those queries with your existing data.

It is a specification that describes the capabilities and characteristics of a client-server communication. Its principle is “Ask for what you need, get exactly that”. It is built in order to give the client the power to specify exactly the data that is needed from the API.

Unlike REST’s URL-Driven approach, GraphQL exposes a single (post)endpoint. Lets the client decide what data is actually needed, nothing less-nothing more, and offers way more freedom to frontend developers. Please see Figure 1 for the difference between multi/single endpoint approaches.

Figure 1: URL driven vs. Query language

Core concepts

The Schema Definition Language (SDL): GraphQL have a strongly typed schema that defines the server’s API. It is an abstract description of the server’s capabilities.

Figure:2 Sample schema definition

Queries & mutations: Is used to modify/add/view/delete our resources. Figure 2 shows a sample query and a mutation.

Is used to modify/add/view/delete our resources. Figure 2 shows a sample query and a mutation. Subscriptions: Is used to get realtime updates about our resources. Figure 2 shows a sample subscription that makes a notification to subscribers when new Person is added.

Is used to get realtime updates about our resources. Figure 2 shows a sample subscription that makes a notification to subscribers when new Person is added. Resolver functions: Every field on every type is backed by a resolver. Each resolver knows how to fetch the data for its field. Query results are fetched by invoking all the resolver functions for the fields specified in the query.

The structure of a GraphQL server is defined in its schema. The concrete implementation of server behaviour is in its resolver functions.

We’ll dive deep on these concepts later on this post.

Let’s take an example

In order to clarify how GraphQL works, let’s consider an example. I’ll be using SWAPI(The Star Wars API) REST and GraphQL public API’s to illustrate what’s going on behind the scenes. You can use these public API’s as a playground to a better understanding.

Assume we need to display following information about the starship with id:10

Starship Name

Starship Model

All Pilots’ name, gender and eye color

REST implementation:

We first need to make a GET request to starships endpoint. As you can see, response object has more fields, shortened for simplicity.

Figure 3: REST starships request

Then we make 4 GET requests for each people, to people endpoint, one of them is shown below:

Figure 4: REST people request

Please note that we needed to make 5 requests in order to get what we want. Now we also have more information than we need. For instance, we’re not interested in a cargo capacity of a starship.

GraphQL implementation:

In GraphQL implementation, we only need 1 request as shown in Figure 5.

Figure 5 : GraphQL implementation

We just needed 1 request and got exactly what we need. Nothing less, nothing more.

How GraphQL works?

Client sends a request to server, then following steps should be run on server side:

Parse : Server needs to parse the request.

: Server needs to parse the request. Validate: Server needs to apply schema validation rules, complexity constraints, avoiding circular dependencies etc.

Server needs to apply schema validation rules, complexity constraints, avoiding circular dependencies etc. Execute: Executes query via resolver functions.

Let’s take a closer look at our resolver functions:

As I said earlier on this post, every field on every type is backed by a resolver. In order to fulfill any query request, server needs to implement an algorithm to fetch all related fields’ data using their resolver methods.

Figure 6: Resolver functions

The tree is executed breadth-first. Starship must be resolved before its children: name, model and pilots are executed. If the starship resolver is asynchronous, the pilots branch delays until its resolved. Once all leaf nodes are resolved, execution is complete.

For more about breadth-first search, visit wikipedia page.

Tools and Libraries

You don’t have to implement all above. There are some tools&libraries to help you on the implementation: client side as well as the server side, such as Apollo and Relay.

GraphQL PROS

No Overfetching and Underfetching:

Overfetching means that a client downloads more information than is actually required in the app. Under-fetching or the n+1 problem is not having enough data with a call to an endpoint, forcing you to call a second endpoint.

In our example above, in REST implementation, we got more fields than we want(See Figure 3&4). This causes over using of network resources.

Secondly, starship endpoint cannot provide pilot information. We are forced to make 4 more requests to people endpoint.(See Figure 3&4). This is an example of under-fetching problem.

GraphQL solves this efficiency problem by fetching the exact data in a single request.

Fast development & rapid feature development & Increased creativity on the frontend side

Let’s think about a case where we need extra field(birth year of pilots), in our example. It is simple as the client adds one more field to its query. That’all.

No need to develop anything on the server side since all fields are defined in schema definition.

GraphQL APIs have a strongly typed schema

Auto-generated API documentation is available out-of-the-box. You might even get auto-completion for API operations in your editor.

Mocking is easy!

Figure 7: SWAPI Auto completion and API documentation

Composing GraphQL APIs: It provides the ability to run nested queries as I explained in resolver functions.

Realtime Updates with Subscriptions: Client can subscribe to a specific resource and get notifications.

Insightful analytics on backend: Backend will know which datas are frequently used on clients and which are useless.

GraphQL CONS:

Security and performance issues: With great power comes great responsibilities. The client can potentially take your GraphQL server down. Server code needs to handle things like avoiding complex nested queries and circular loops.

File uploading a file uploading feature is not included in its specification, although it is possible with some workaround.

Server-side caching still is a challenge with GraphQL. Unlike REST, the structure of the response data may change. It uses a single endpoint instead of following the HTTP specification for caching. To have cache on GraphQL you have to setup your own.

Error handling: Single endpoint always returns 200. Unlike REST’s built-in error structure, you need to implement your own.

Complexity and the learning curve: Unlike REST’s simple and easy architecture that uses standart http methods, GraphQL adds more complexity(like resolver functions, validations).

Combined Solution: Wrapping a REST API with GraphQL

As we all know, It’s not easy to replace legacy architectures with another. Since REST API’s do well in most cases, it would be hard to justify an additional investment in GraphQL infrastructure from scratch.

As I said earlier on this post, GraphQL is only a specification and doesn’t care about where you fetch the data. It can be a db, it can be a cloud server or REST API.

Without Big Bang Data Migration, the smoothest way to migrate from REST to GraphQL may be to keep REST API’s for fetching purposes and wrap them with GraphQL.

Final thoughts…

Especially for the last 2 decades, increased mobile usage created a need for more efficient data loading. Expectations for faster feature development are rising day by day. GraphQL, a modern alternative, aims at solving REST’s shortcomings. However, it also introduces a new set of challenges which need to be evaluated.

Do I have to migrate our API’s from REST to GraphQL now? It is important to understand the tradeoffs before making such architectural decisions. If your API’s are to be consumed by a mobile app, go for GraphQL. If you need a robust API you may choose REST.

The good news is: You don’t have to pick between one and the other, they can easily co-exist in the same project.

Resources