DEV Community

Cover image for GraphQL vs REST: Which API Type is Right for Your Application?
Mufassir Kazi
Mufassir Kazi

Posted on • Originally published at mufassirkazi.hashnode.dev

GraphQL vs REST: Which API Type is Right for Your Application?

REST and GraphQL APIs are the developer's top choices for API design. With conflicting opinions on the internet, it's easy to get lost when debating which API type would make the most sense for your application.

Before we do a deep dive, let's have a look at some of the common terminologies used while discussing APIs:

Resource
It is the basic building block of a RESTful service. When you pull information from a server (backend) to display on the client side (frontend), you are essentially fetching a resource. There are various HTTP methods (next point) you can perform on a resource.

Eg. For an airline platform, flight_name, flight_details, and no_of_passengers for a flight are examples of a resource.

GET /flights/today
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "flight_name": "Airbus D-545-341",
  "flight_details": { 
    "flight_name": "Hawaiian Airlines",
    "flight_number": "N324KS",
    "flight_to": "Los Angeles"
  },
  "no_of_passengers": 284,
  "time_of_departure": "730 PM GMT"
},
{
  "flight_name": "Airbus D-325-536",
  "flight_details": { 
    "flight_name": "Hawaiian Airlines",
    "flight_number": "L5DFD",
    "flight_to": "Los Angeles"
  },
  "no_of_passengers": 281,
  "time_of_departure": "530 PM GMT"
},

  // ... more fields here
Enter fullscreen mode Exit fullscreen mode

HTTP methods:
Below are listed some of the most common types of HTTP methods.

GET: Used in read-only mode, GET is the most common HTTP method. It is used to get a representational view of a resource's existing content.

POST: This method enables developers to create a new resource. The data to be sent to the server is given in the request body.

PUT: Updates / replaces all the existing resource's content. The new data is sent in the request body to the server.

PATCH: Though not commonly used, PATCH, like PUT, updates a resource's content but just partially. To simply put (no pun intended), it modifies an existing resource.

DELETE: It deletes a resource.

Data fetching 
As the name suggests, data fetching is fetching data from the server to display on the client. With REST, it introduces drawbacks like "overfetching" or "under fetching". GraphQL, on the other hand, uses a query based approach which mitigates these drawbacks (more on this later).

Caching
It is the process of generating a cache which stores a subset of a data. This data then can be served up faster during future requests as they are already prefetched.

What is a REST API?

The successor of SOAP API, REST is a flexible, scalable, and easy to use architectural style. It was introduced as a simpler way to do server side communication.

REST Structure

A typical structure of a REST API consist of an endpoint, HTTP method, header and body.

  • An endpoint includes the URL of a server or service that helps to identify the resource to be fetched.
  • You can specify the type of request that is to be sent to the server by using the HTTP methods described above.
  • Headers are useful to provide information like caching, authentication tokens, etc to the client and server.
  • The body consists of payload / information that a client wants to send to the server.

Okay, what is GraphQL then?

GraphQL structure

GraphQL uses a "query" based approach where you execute queries in a single request. You do not target different endpoints, instead, you specify what you want in the request body. The content inside the request body is in the form of GraphQL query which is parsed on the backend. 

This is a standardised approach and therefore there are rules defining how it should be parsed and what commands one can use, similar to how you would query a database.

The declarative vs imperative approach

Think of it this way - You are at a grocery store going through your shopping list and self guiding yourself based on signs at end of each row. You find the items you need, fill your cart, then continue to checkout. It's imperative because it requires you to know where all items are stocked up. REST approach is similar. You have endpoints and you fetch resources from these different endpoints to source your app.

GraphQL, on the other hand, follows a declarative approach. It's more like you have a personal assistant who goes and picks all items for you. The only thing you need is to 'declare' the items you need.

Why not to REST

Problems with REST API
1. Data fetching (again)
As discussed previously, REST API has a drawback of "underfetching" and "overfetching". Taking our airline platform example from earlier, suppose you only want details of all flights scheduled for the day.

In case of REST, when you hit the endpoint /flights/today, instead of just returning the flights information, it'll also include all other information that the endpoint has to offer i.e noOfPassengers, timings, airlineInfo, etc. This idea of fetching more information than necessary is termed as "overfetching". Vice versa, "underfetching" is when the request doesn't return adequate information requiring you to make multiple calls on different endpoints for different resources.

In case of GraphQL, you use a single request that can access data from multiple sources. Due to the query data structure, GraphQL allows you to precisely specify the type of data you want to receive from the server. This keeps your code concise and efficient.

2. Performance
Because REST has a drawback of overfetching, it returns a data set much larger than what is actually required. Of course, a lot largely depends on how the API is designed, but with REST, there is only so much you can specify.

For example, let's study the request below.

GET /dishes/details
Enter fullscreen mode Exit fullscreen mode

This is an example of a REST call to get a list of all food dishes served in a restaurant. The data returned for a single dish is:

{
  "dish_name": "Apple Pie",
  "preparation_time": "170 mins.",
  "price": "$9.83",
  "ingredients": "2 1/2 cups all-purpose flour, 4 teaspoons sugar, 1/4 teaspoon fine salt, 14 tablespoons cold butter, diced, 1 large egg, 2 tablespoons freshly squeezed lemon juice, 3 pounds baking apples like Golden Delicious, Cortland, or Mutsu, 2/3 cup sugar, plus more for sprinkling on the pie, 1/4 cup unsalted butter, 1/4 teaspoon ground cinnamon, Generous pinch of ground nutmeg, 1 large egg, lightly beaten"
},

//More dishes here
Enter fullscreen mode Exit fullscreen mode

The problem arises when you want only the dish_name and price property to be returned from the request. REST API doesn't allow you to extract specific properties from a given data set.

On the other hand, with GraphQL this is not the case. GraphQL API allows you to define the data you need and returns that only - no more, no less. This avoids a lot of unwanted data and the returned output is much smaller, thereby improving performance.

An example of a GraphQL query is as follows:

{
  restaurantDishes(limit: 3) {
   dish_name
   price
  }
}
Enter fullscreen mode Exit fullscreen mode

And the response:

{
  "data": {
    "restaurantDishes": [
      {
        "dish_name": "Apple Pie",
        "price": "$9.83"
      },
      {
        "dish_name": "Fried Chicken",
        "price": "$29.99"
      },
      {
        "dish_name": "Cheeseburger",
        "price": "$1.39"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Schema and Type safety
GraphQL uses its own type system - SDL(Schema Definition Language). A schema defines how a client can access resources from the server. 

This helps in catching errors easily while allowing the front-end and backend teams to work independently. GraphQL also allows you to stitch multiple schemas together so that a client can access data from different sources. 

For REST, this would mean making multiple API calls at different endpoints. This can result in more computational power and lower efficiency.

4. Speed of Development
Because GraphQL allows you to specify the query on the fly, front-end developers can adjust response requirements without backend involvement. 
Same is not true for REST though. REST APIs are structured according to endpoints and the data they return (e.g: /price, /ingredients, /dishnames, etc). To adjust response requirements, one may need to fetch data from different endpoints and be prone to the classic problem of underfetching / overfetching.

Problems with GraphQL

Problems with GraphQ

1. Learning curve
Despite its many advantages, GraphQL falls short on REST because of simplicity. If you're new to development, REST is much easier to learn between the two having no restrictions on what your resource can consume or return.

2. HTTP Caching
In REST, the URLs for the requests are different (GET, POST, PUT, PATCH, DELETE). This allows you to get a globally unique identifier for an object which helps you to implement an HTTP cache. This way, you can easily identify if two resources are same while also allowing you to avoid fetching the same resource twice.

Meanwhile, in GraphQL, you use a single endpoint. For non-mutable queries, the developer has to ensure that caching is setup manually and the correct key is being used to inspect the body elements. There are tools that cover GraphQL semantics, but most of them lack in things like mobile and browser caching.

3. Resource attacks
The most talked benefit of GraphQL allowing clients to query only the data they need comes with a huge drawback - performance. Open APIs used in an app do not allow you to control 3rd party client query behaviour. This can results in expensive join queries which can severely effect server performance, or worse, result in a DDoS attack.

4. Reporting (Errors)
As REST follows the HTTP spec, it allows many tools to probe a URL endpoint and study error messages if not OK. In GraphQL, these tools cannot help. GraphQL client errors always return a 200 OK status response with a Something went wrong message. As this is superficial, it is very difficult to handle and monitor errors on GraphQL.

Best practices to follow while designing your next API

Best practices to follow while designing your next API
1. Security first
All client - server communications should be protected by SSL / TLS. Your API should communicate over a secure channel thereby restricting users to only access information they requested and nothing more. Moving a step further, you can enforce a roles check for an admin role or have granular roles depending on your application.

2. Use nouns for endpoint paths
HTTP request methods are made up of verbs ( GET, POST, PUT, PATCH, DELETE). Adding another verb as an endpoint path will make your request difficult to comprehend. The action of the request should be defined by the HTTP method while your path can define the resource on which the action is being performed. Eg: You can make your routes self explanatory like GET/flights gets all the flights, DELETE/flight/:id is for deleting the flight matching the given id.

3. Control your data
As you scale, your data sets can get very large. Depending on the request, you might end up returning a large amount of data in a single request that will slow down your network and crash your systems. This is where filtering comes in. Allow data to be filtered and paginated so that in case of such a request, we return only a finite number of results at a time. This also helps in increasing performance and reducing server costs.

4. Versioning 
Especially useful in public API settings, versioning allows your users to transition overtime to upgraded versions of your API changes (goodUX). Like most apps, you can follow the semantic version for versioning - eg: 1.0.4 indicates major version 1 and the 4th patch. This allows your users to keep using the older version in case they are not ready to upgrade or access the new release with the latest features. Also, this helps to avoid failure in third party apps that can still be accessing the older version of the API.

5. Caching
We learned earlier in the article what caching is and how it helps to improve performance of your system. However, there can be times when the data gets outdated. This creates issues in testing as we continue to see old data. To resolve this, you can use a caching solution like Redis or implement in-memory caching. This way, as your needs change, you can change the way your data is being cached.

6. Configuring your request and responses headers
This helps to specify information about the request being made. In return, it also specifies information on how a response was generated. Apart from this, you can also configure timeout settings to retry requests if they fail due to server or network errors.

Conclusion: Which API type will make the most sense for my application?

Honestly speaking, it depends on your application. Many times, instead of debating over REST vs GraphQL, a basic API for a basic site with focused endpoints would suffice (releasing the developer from unnecessary complexities).

That being said, REST is widely used for a simple reason: simplicity. Ground rule is if you don't have to combine data types in custom ways or are flexible in the kind of data your request returns, it's easier to keep things simple with REST. With REST, you can target a wide range of apps and users in the simplest way possible, especially when you don't know who or how your API is going to be consumed.

Meanwhile, GraphQL comes in the picture when you realise that you'd need multiple REST queries to perform a certain action. Instead of creating 10000 different endpoints to fetch minimised versions of your data set, use GraphQL to define what and how much of the data you need.

Ultimately, it all boils down to understanding your product and code architecture. As a closure, a well designed API is much important over the type of API that you end up using.


Hey there👋!

My name is Mufassir and I work as a Product Manager at a dev tool startup.

Thank you so much for reading till the end 💙. For reach-outs, I’m available on LinkedIn or feel free to follow me on Twitter.

Top comments (0)