GraphQL vs REST API

TL;DR

Addressing the ongoing API debate about whether to choose GraphQL or REST, we set out to break down both options in a thorough comparison article. First, we go into the main definitions of GraphQL and REST APIs and then, you will find out:

  • The six REST constraints: client-server architecture, is stateless and cacheable, has a uniform interface, a layered system and you have the option of using Code-On-Demand.
  • REST has the advantages of being a popular API, that is easy to understand, as well as scalable.
  • GraphQL is more complex than REST, and its main drawbacks include issues with error reporting, caching, and N+1.
  • However, GraphQL solves the over and under-fetching problem that REST has, is protocol agnostic and has a quick response time.

The battle between GraphQL vs REST has been ongoing for quite some time. Primarily, because these two API styles have a different approach when dealing with the transfer of data over internet protocols.

Creating an Application Programming Interface(API), used to be limited to deploying and consuming.

Now, as the API universe is expanding, a lot goes into building it: right from the design phase all the way up to the final release. One of the major aspects to consider while designing an API is the architecture that is appropriate to fit the needs of the business. When building and consuming an API, developers are usually faced with a dilemma as to which is the right architecture to choose: REST API or GraphQL.

While REST API may seem like the de-facto option for API creation, GraphQL has gained momentum due to its high adoption rate, and is now seen as a revolutionary alternative to REST API. Before diving deep into the differences between GraphQL vs REST API, as well as their pros and cons, let's first understand what they are and their mechanisms.

[@portabletext/react] Unknown block type "newsletter", specify a component for it in the `components.types` prop

What is REST and RESTful API?

REST(Representational State Transfer) is an architectural style that conforms to a set of constraints when developing web services. It was introduced by Roy Fielding as an alternative to the complex method of SOAP (The Simple Object Access Protocol) in the year 2000 while presenting his Ph.D. dissertation.

RESTful API is a Web Service API that follows the REST standards. Unlike SOAP, a REST API is not constrained to an XML format and can return multiple data formats depending on what is needed.The data formats supported by REST API include but are not limited to:

  • application/json
  • application/xml
  • multipart/form-data

How does REST API work?

When a client calls a RESTful API, the server transfers the representation of the state of the resource to the client in a standardized representation. REST API works by returning information about the source that was requested by the client. This information is then translated into a format that is easily interpreted by the client. Through REST API, clients can modify or add new items to the server.

What is the Structure of a REST request?

A REST request is made up of four essential parts:

  • endpoint
  • HTTP method
  • Headers
  • Body

An endpoint contains a URI (Uniform Resource Identifier) that helps in identifying the resource on the internet.

An HTTP method describes the type of request that is sent to the server. They are:

  • GET - The GET method reads a representation of a specified source.
  • POST - The POST method is used to create a new specified source.
  • PUT - The PUT method is used to either update/replace every resource in a collection.
  • PATCH - THE PATCH method is used to make modifications to a source.
  • DELETE - Deletes a specified source.

When working with data, a RESTful API uses HTTP methods to perform CRUD (Create, Read, Update and Delete) operations.

Headers provide information to client and server usually for authentication purposes.

A body contains information that a client wants to send to a server, such as a piece of data that needs to be added or replaced.

What are some REST constraints to consider when designing a REST API?

Although the REST API is a simple interaction system that efficiently performs operations and returns data via HTTP protocols, we need to keep in mind that not all HTTP APIs are REST APIs -- as there are different kinds of API types. The following architectural requirements need to be taken into account while considering REST APIs. The six constraints are:

  • Client-server architecture: Client and server applications need to have a clear boundary between the components and must evolve separately without being dependent on each other. For e.g,the client makes a request to the server using the URL and the data that is sent back from the server acts as a response. This not only improves the portability of the user interface across multiple platforms but also supports the scalability of multiple organizational domains.
  • Stateless: The client-server architecture must be stateless. This means that the server will not store any HTTP requests made by the client and will treat each request as a new one. No history is stored on the server-side and each session state is entirely on the client-side thus making the client responsible for the state of the application.
  • Cacheable: According to Cache constraints, the API responses made either implicitly or explicitly must be labeled as cacheable or non-cacheable. If the response is cacheable, a client can cache any representation, thus giving the right to reuse the response data in the future.
  • Uniform interface: What separates REST architectural style from other network-based styles is the emphasis on a uniform interaction with a given server irrespective of the device or application type.
  • Layered System: This REST constraint allows you to use a layered system for your application architecture. This means that you can deploy APIs, store data and authenticate requests on different servers without the client being aware of the intermediary process. Intermediaries enable load balancing of services across multiple networks thus improving system scalability.
  • Code-On-Demand: The final addition to the REST constraints, is Code-on-Demand (a completely optional one). When necessary, this constraint allows client functionalities to be extended by downloading and returning an executable code from the server in the form of applets or scripts instead of returning a JSON representation.

For example, a client downloads a Java applet or a JavaScript code from the server.

However, this constraint has its own risks as you could download code from an unreliable source thereby compromising on your security level.

REST API Example:

To have a better grasp of the concepts of REST API, let’s take a look at the base url of the Rick and Morty API: https://rickandmortyapi.com/api

The Rick and Morty API has three available resources e.g:

  • Character: gets all the information related to the characters.
  • Location: gets information related to all the locations.
  • Episode: gets information related to all the episodes.

Suppose a client needs information about the name and state of a character, then the server creates the representation of a resource and responds back to the client in a data returned in json format.

With REST, the endpoint looks like this:

GET https://rickandmortyapi.com/api/character/?name=morty&status=alive

The server responds with the following data:

{
  "id": 27,
  "name": "Artist Morty",
  "status": "Alive",
  "species": "Human",
  "type": "",
  "gender": "Male",
  "origin": {
    "name": "unknown",
    "url": ""
  },
  "location": {
    "name": "Citadel of Ricks",
    "url": "https://rickandmortyapi.com/api/location/3"
  },
  "image": "https://rickandmortyapi.com/api/character/avatar/27.jpeg",
  "episode": [
    "https://rickandmortyapi.com/api/episode/10",
    "https://rickandmortyapi.com/api/episode/28"
  ],
  "url": "https://rickandmortyapi.com/api/character/27",
  "created": "2017-11-05T08:59:07.457Z"
}

REST API Testing:

One of the best ways to test REST API is by using the Postman application.This tool is extremely helpful as you can structure the HTTP requests and try out various HTTP methods.

What are the Main Advantages of using REST APIs?

Some of the benefits to note while creating a REST API are:

  • It's easy to understand: Easier to adapt to REST principles while building an API since it uses HTTP methods. Most of the HTTP verbs are pretty self-explanatory and easy to understand.
  • Popularity: A dominant API infrastructure in the market between 2011-2015, REST still stands out as the most widely used architectural style for web services due to its rich ecosystem. According to Google Trends, you can see that REST continues to be a popular architectural style for API design compared to GraphQL.
  • It's scalable: Since there is a separation between the client and server, it is easier for different teams to work on different parts of the application. This allows for the application to be scaled by the development team without increasing the complexity
  • Caching: REST has built-in caching that minimizes multiple trips to the server. When a client makes a request to the server, it checks for the first cache. If the cache exists, it will not proceed to the server. Caching in REST acts as an intermediary layer since frequent queries are stored for reusability.
  • Data formats: REST APIs can handle many types of data requests and multiple data formats.
  • Code Encapsulation: When REST is used as an architectural style for API design, it allows for code encapsulation. This means that a particular piece of code that is part of an application can be concealed while displaying the rest of it to the client.
  • Communication: REST API communicates via HTTP status codes to let us know if the request was successful or whether an error was encountered. The status codes are grouped into five classes, they are:

    1. Informational responses(100+) - A 100+ status code indicates that either the client could continue with the request or ignore it if it is already finished.
    2. Successful response(200+) - A 200+ status code indicates the success of a request.
    3. Redirection message(300+) - A 300+ status code signals that a request has been redirected to another URL.
    4. Client error responses(400+) - A 400+ status code could indicate an error in the clients request meaning that there could be an invalid data or an error in the message.
    5. Server error responses(500+) - A 500+ status code indicates an error that was not processed on the server side.

What are the main Disadvantages of using REST APIs?

Not everything is perfect, there are also some downsides to using REST APIs, some of them are:

  • Overfetching/Underfetching: The biggest drawback in REST API is that it is highly susceptible to over-fetching and under-fetching. Over-fetching happens when we get more data than it is required. For example, when we need a list of characters related to a tv series, we do not need every information related to these characters. Similarly, when it comes to over-fetching, a particular endpoint might not give the required information. This leads to calling two endpoints for one view thus slowing down the response of an application.
  • Versioning: APIs can have different versions due to compatibility issues. However, more versions of an API makes the code less maintainable.
  • Limited bandwidth: To process a bigger payload, you will need a network pipe with a higher bandwidth capacity. REST can only be used when the constraints of a network bandwidth are limited.

GraphQL

Developed internally by Facebook in 2012 before publicly releasing it in 2015, GraphQL is an open-source query language that is often touted as an alternative to REST API. Just like REST API, GraphQL is an architectural style for delivering data using HTTP method. GraphQL was designed to address the ongoing problems of REST API such as data-fetching and multiple endpoints. A common misconception with GraphQL is that it is a database technology however that isn’t the case. Just like REST, GraphQL is used to either retrieve or modify the data.

How does GraphQL work?

GraphQL revolves around these major components: queries, mutations, resolvers and schema.

  • Queries: Queries is the process of fetching data from the GraphQL server. Mutations: Mutations is the process of writing and modifying data on the GraphQL server.
  • Resolvers: Since servers don't know what to do with the incoming queries, resolvers act as an assistant by telling GraphQL where and how to fetch data corresponding to a given field.
  • Schema: schemas describe the functionality a client can utilize when it is connected to a GraphQL server.

Here's a GraphQL Example for to help us visualize it:

Being a query language, GraphQL tailors requests following the requirements of a client and responds in a JSON format only when the requirements are fulfilled.

e.g- Considering the same scenario in REST case, GraphQL makes a single query to the server to fetch the name and status of a character:

query {
  characters(filter: { name: "rick" }) {
    results {
      name
      status
    }
  }
}

The JSON response

{
  "data": {
    "characters": {
      "results": [
        {
          "name": "Rick Sanchez",
          "status": "Alive"
        },
        {
          "name": "Adjudicator Rick",
          "status": "Dead"
        },
        {
          "name": "Alien Rick",
          "status": "unknown"
        },
        {
          "name": "Antenna Rick",
          "status": "unknown"
        },
        {
          "name": "Aqua Rick",
          "status": "unknown"
        },
        {
          "name": "Black Rick",
          "status": "Alive"
        },
        {
          "name": "Bootleg Portal Chemist Rick",
          "status": "Dead"
        },
        {
          "name": "Commander Rick",
          "status": "Dead"
        },
        {
          "name": "Cool Rick",
          "status": "Alive"
        },
        {
          "name": "Cop Rick",
          "status": "Alive"
        }
      ]
    }
  }
}

Let's now have a look at how Testing looks in GraphQL:

The GraphiQL or GraphQL Playground is extremely useful when running your queries and mutations to inspect/test your API.

Another option for testing the GraphQL API is using Postman as it has an inbuilt support to run GraphQL queries. Postman supports working with GraphQL by:

  • Sending GraphQL queries as POST requests.
  • Supporting GraphQL variables.
  • Creating/Importing GraphQL schemas.
  • Query autocompletion.

What are the Advantages of GraphQL?

  • Solving the over and under-fetching problem: Unlike REST, GraphQL sends a single query to the server according to the data requirements. The server then responds with a JSON object when the requirements are fulfilled.With GraphQL, it returns the requested data according to the needs of the client, thus minimizing network and memory use for clients.
  • Schema and Type System: GraphQL is strongly typed which means that it allows users the type of data that is available and the form it exists in.
  • Protocol agnostic: Although GraphQL typically serves over HTTP, it isn’t the only choice when it comes to client-server communication since it is agnostic to the transport layer. You could use any protocol as long as you can retrieve or manipulate a piece of data. This is useful in scenarios where WebSockets can be used for real-time updates instead of HTTP.
  • Quick response time: Since you can combine multiple requests together and get the exact data using a single endpoint, it lowers the latency time resulting in a quick response time.
  • Flexibility: With GraphQL you can add new fields and data types without worrying about changing the frontend code or creating a new version for your API.
  • Schema stitching: GraphQL can combine multiple schemas into a single schema to make it accessible to the client. For example, merging the schemas of Universe API and Dark Sky API by getting the details of a particular event and the weather of the city into a single schema.
query {
  event(id: "5879ad8f6672e70036d58ba5") {
    title
    address

    host {
      firstName
    }
    timeSlots {
      totalCount
      nodes {
        startAt
      }
    }
  }
  location(place: "Los Angeles") {
    city
    weather {
      summary
      temperature
    }
  }
}

and response:

{
  "data": {
    "event": {
      "title": "End of Unix Time",
      "address": "Los Angeles, CA, USA",
      "host": {
        "firstName": "Joshua"
      },
      "timeSlots": {
        "totalCount": 2,
        "nodes": [
          {
            "startAt": "2018-08-31T12:00:00"
          },
          {
            "startAt": "2038-01-18T21:00:00"
          }
        ]
      }
    }
  },
  "location": {
    "city": "Los Angeles",
    "weather": {
      "summary": "Cloudy with periods of rain",
      "temperature": 77
    }
  }
}
  • Introspection: To know more information about the type of queries supported in a schema, GraphQL introduces a feature known as Introspection. With introspection, developers can see the queries, types, fields and directives that are supported in the current schema. Through introspection, you don’t have to worry about API documentation since the document is generated automatically.
{
  __schema {
    types {
      name
      description
    }
  }
}

and response:

{
  "data": {
    "__schema": {
      "types": [
        {
          "name": "String",
          "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text."
        },
        {
          "name": "__Schema",
          "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations."
        }
      ]
    }
  }
}
  • Rapid Development on the Frontend: Under REST API, frontend developers usually need to wait for backend developers to finish developing the API .Through the GraphQL approach, frontend developers need not have to wait for an endpoint from a backend developer and can retrieve the exact content according to the queries.
  • Real-time data: Apart from queries and mutations, GraphQL also supports another operation type i.e, subscriptions. With subscriptions you can fetch data each time there is an update in the result. This is particularly useful when building real-time applications as clients are notified about ongoing changes.

The Main Disadvantages of GraphQL

  • Error reporting: The queries will always return an HTTP status code of 200 regardless of whether the query was successful or not.
  • Security: When working for an API, GraphQL lets you query your requests according to your needs. Although this gives enormous power to the clients, it has security implications since complex queries can overload your server and network thus exposing yourself to a DoS attack.
  • N+1 problem: One of the common pitfalls when dealing with GraphQL performance is the N+1 problem.The reason developers are prone to this issue is because GraphQL executes a separate resolver function for every field.Due to the nested data, servers will need to make multiple, unnecessary round trips to the datastore.This is not the case in REST as there is one resolver for every endpoint.
  • Caching: GraphQL lacks the inbuilt caching system since it does not follow the HTTP specification and instead uses a single endpoint. Since it does not have a cache support of its own, GraphQL will need to rely on an external library like FilamentQL to provide client-side as well as server-side caching solutions. Alternatively, a CDN such as GraphCDN can be used to scale as well as protect your API from random traffic spikes, database troubles and downtime.
  • Introspection: While introspection has its advantages, one must be extremely cautious when implementing the mechanisms of introspection especially in production mode as it can reveal the backend created by developers such as arguments, fields,types,descriptions,etc. If the entire backend is exposed, attackers could retrieve fields that are normally not accessible for users.
  • Complex: GraphQL can be a bit complex to understand as it has a steep learning curve compared to REST and is best suited for companies that are dealing with rapidly-changing data and have the resources to re-architect their API platforms.
  • File Uploading: Uploading files to a GraphQL API is not a straightforward task since there isn’t much information about it on the official GraphQL documentation and one might have to consider switching to REST. For that the file needs to be uploaded via REST endpoints and the resulting URL will then be passed to the GraphQL mutation. Alternatively, it is possible to upload files through Apollo server via third-party library i.e, graphql-upload.
  • Performance issue: Complex queries could slow down the performance of an application. To process each request, GraphQL would have to impose an additional time cost. Solution:To counter the performance issue, it is possible to use a native GraphQL database such as Dgraph to handle millisecond query response time even on complex queries.

Comparison Table between REST and GraphQL

The core differences between REST and GraphQL are:

REST

vs

GRAPHQL
A server-driven architecture.
A client-driven architecture.
Need to make multiple API calls.
Prevents multiple API calls unlike REST.
Has no concept of schema/type system.
GraphQL is strongly typed which means that it helps in defining what an API looks like.
Fetching little or more than the required data which could lead to over-fetching or under-fetching.
Solves the problem of over-fetching.
Weak performance in mobile applications.
Built to address the performance issues of a mobile application.
Has an in-built cache support.
Does not have an in-built caching support system.
Suitable for small applications with consistent data. REST usually focuses on standard client to server communication.
Ideally used by companies when dealing with complex, cross- platform applications and rapidly changing data.
Handles multiple HTTP status codes to communicate with the client.
Returns a 200 status code irrespective of the success of the query.
Can support multiple data formats.
Returns the data in JSON format.
Hard to maintain consistency across platforms.
Consistent across a variety of platforms.
REST uses various HTTP methods such as GET, POST, PUT, PATCH, etc for either retrieving or modifying the data.
Usually the GraphQL queries are performed using the HTTP POST request method.
One query can handle only one router function each time.
Single query can call various resolvers to fetch data from multiple resources.
A widely accepted standard with a mature ecosystem.
Seen as a revolutionary alternative to REST however it is not implemented that often.
Gets challenging to maintain different versions of a REST API.
Need not worry about maintaining old versions of API as GraphQL has @deprecated annotation that lets the client know which field can no longer be used while also maintaining.

Conclusion

When choosing between GraphQL vs REST, we need to consider certain aspects such as the skill set of developers, the number of data sources and changes in the data sources. Ideally, if you’re dealing with a lot of data sources, GraphQL would be a better choice as you can abstract data sources at the backend and invoke the requested data. Similarly, if you’re dealing with frequent changes in the data source, GraphQL is suitable as you can swap the resolvers easily.

According to a study founded by ProgrammableWeb in 2017, roughly 80% of APIs were designed in REST style. REST is suitable in scenarios where developers with a tight schedule are comfortable in designing the API according to REST constraints. Also who controls the client is equally important since GraphQL is client-centric and not being able to control the client would make it difficult to deploy a graphql client.

Deciding which API technology is better than the other is not an easy task as REST and GraphQL both have their pros and cons. GraphQL was primarily created to deal with the shortages of REST API such as avoiding multiple round trips and offering better bandwidth due to the shift in mobile applications. However, GraphQL fails to deal with issues related to monitoring and error reporting. In this case, REST has the upper-hand as it returns HTTP status codes according to the error.

Choosing an API design architecture ultimately boils down to the requirements of the business. It wouldn’t be wise to assume that a particular architectural style fulfills every application's requirements. To get the best of both worlds, a combination of REST and GraphQL can be useful in dealing with different scenarios.