We’ve established that GraphQL and REST are two popular, yet distinct approaches to designing APIs for exchanging data. REST enables client apps to exchange datausing HTTP, which is the standard communication protocol. On the other hand, GraphQL is an API query language that defines specifications of how a client app should request data from a server. You can use GraphQL in your API calls without relying on the server-side application to define the request. So before diving into the differences between the two, let’s take a quick look at what they share in common.
Similarities between REST and GraphQL
Architecture
Both, REST and GraphQL, are stateless, so the server doesn’t save response histories between requests. And since they’re both using client-server models, requests from a single client results in replies from a single server (i.e. one query hits one endpoint).
Resource-based Design
REST and GraphQL both design their data interchange around resources, which is any data or object that the client can access through the API. Each resource has its own unique identifier and a set of operations that the client can perform on it.
For example, consider a menu API where users create and manage products. In a resource-based API, a product could be a resource. It has its own unique identifier, for example, /menu/pizza-diavola
, and it has a set of operations, such as GET
to retrieve the product in REST or a query to retrieve the product in GraphQL.
Language and database neutrality
Both REST and GraphQL support similar data formats, more importantly, open ones, since neither generates proprietary gibberish in their standard applications. JSON is the most popular exchange format that all languages, platforms, and systems understand. The server returns structured JSON to the client. At times, some other data formats like XML and HTML are available but less common.
That being said, GraphQL emerged as a successor to REST (more specifically, by Facebook, to sort out their mobile app performance issues) to try and overcome some of its limitations, most notably, Fixed-structure data exchange, and the issue of Over/Under-fetching.
REST requires client requests to follow a fixed structure to receive a resource. This rigid structure is easy to use, but it’s not always the most efficient means to exchange exactly the data needed.
Further, REST always returns a whole dataset. For example, from a product object in the REST API, you would receive everything the endpoint has about the product (like the price, ingredients, pictures, etc.) even if you just wanted to get the pizza’s name.
If you wanted to know the pizza’s ingredients and price, you would need multiple API requests. GraphQL emerged as a query-based solution. Queries can return the exact data in only one API request and response exchange.
So let’s take a look at the differences.
Difference between REST and GraphQL
The core difference between GraphQL and REST APIs is that GraphQL is a specification, a query language, while REST is an architectural concept for network-based software. GraphQL operates over a single endpoint using HTTP.
GraphQL is great for being strongly typed, and self-documenting based on schema types and descriptions and integrates with code generator tools to reduce development time. In addition, REST development has been more focused on making new APIs. Meanwhile, GraphQL’s focus has been on API performance and flexibility.
Here’s some of the criteria where we see notable differences, saving the best for last.
Client-side Requests
So how do REST requests actually work?
First, you’ve got HTTP verbs that determine the action, like
GET
.Then, there’s a URL that identifies the resource on which to action the HTTP verb, like the menu endpoint from where you can
GET
the data.And finally, parameters and values to parse, if you want to create or modify an object within an existing server-side resource.
For example, you use GET
to get read-only data from a resource, POST
to add a new resource entry, or PUT
to update a resource.
In contrast, here’s what GraphQL requests use:
A query for getting read-only data
Mutations for modifying data in the database
And subscriptions to receive event-based or streaming data updates (listening for changes in real time rather than having to query for changes)
A data format describes how you would like the server to return the data, including objects and fields that match the schema. You can also input new data using Mutations. Under the hood though, GraphQL sends every client request as a POST HTTP request.
Versioning
As APIs grow and evolve, their data structures and operations may change. For clients without the knowledge of these changes, it can break their systems or introduce unknown errors.
REST APIs often include versioning in the URL to solve this issue, like https://example.com/api/v1/menu/12341. However, versioning is not mandatory, and it can lead to errors.
GraphQL requires API backward compatibility. So deleted fields return an error message, or those with a deprecated tag return a warning.
Error Handling and Type Safety
GraphQL is a strongly typed API architecture, which means that it requires a detailed description of the data, its structure, and data operations in the schema. Due to the level of detail in the schema, the system can automatically identify request errors and provide useful error messages.
REST APIs are weakly typed, and you must build error handling into the surrounding code. For example, if a PUT request parses a number value as text instead of as an integer, the system does not identify the error automatically.
Schema
GraphQL uses a strongly typed system to define the capabilities of an API. All the types that are exposed in an API are written down in a server-side schema using the GraphQL Schema Definition Language (SDL) and/or code-first, including details like:
Object types and fields that belong to each object (think content models and fields in the CMS abstraction).
Server-side resolver functions that define an operation for each field
The schema explicitly defines types to describe all data available on the system and how clients can access or modify that data. On the other hand, REST APIs do not require a server-side schema. But you can optionally define it for better API design, documentation, and development.
Frontend teams can now work with the typed GraphQL API knowing that if any changes occur from the backend team on the APIs design, they’ll get this instant feedback when querying it from the frontend.
Data Fetching
One of the common limitations of REST out-of-the-box is that of overfetching and underfetching. This happens because the only way for a client to download data is by hitting endpoints that return fixed data sets. It’s very difficult to design the API in a way that it’s able to provide clients with their exact data needs.
Under REST architectures, data is returned to the client from the server in the whole-of-resource structure specified by the server. The following examples show returned data in REST and GraphQL.
With REST, you’re likely to get something like this when hitting the endpoint for pizzas with a GET /pizzas
operation:
[{"id": 1,"title": "The Diavola","description": "Spicy and juicy"},{"id": 2,"title": "The Margherita","description": "The classic”},{"id": 3,"title": "The Hawaiian”,"description": "Are you sure?"}]
Whereas in contrast, GraphQL would provide something along these lines if you queried for specifics like the first pizza on the menu only using GET /graphql?query{pizza{id: 1}}
:
{"data": {"pizzas": [{"id": "1","title": "The Diavola","description": "Spicy and juicy."},]}}
REST vs. GraphQL
Ok, that’s fun, but what does the difference really look like in the use-case of using a Headless CMS, and why should you care?
When thinking of one of the most known differentiations - the differences in expected responses for queries - in very simple terms, let’s go eat a pizza.
Imagine you’re ordering pizza, and you’re craving a Margherita. Now if that was a RESTaurant (so sorry), you get every ingredient in that pizza every time, it’s always going to be the same shape and size.
https://example.com/api/pizza
If you were in a GraphQL restaurant though, you can have it your way. Don’t like basil? Take it off. Describe your pizza however you like. You’re vegan and don’t want cheese? That’s fine too.
{Pizza {CrusttomatoSauceCheese @skip(if: $vegan)}}
Now some pizza enthusiasts would say you could’ve just ordered a PIzza Marinara, but you didn’t know that existed, and the GraphQL API still accommodated your request and gave you exactly what you wanted, no more, no less.
Conversely, if you wanted to gather some information from a specific endpoint, you couldn’t limit the fields that the REST API returns; you’ll always get a complete data set - or overfetching - when using REST APIs out of the box without added configurations.
GraphQL uses its query language to tailor the request to exactly what you need, from multiple objects down to specific fields within each entity. GraphQL would take x endpoint, and it can do a lot with that information, but you have to tell it what you want first.
Using the same example but for ordering pizzas online, the request would simply be to get pizzaItem
, pizzaToppings
, pizzaImage
, and pizzaPrice
from the same pizza model’s fields, within one request, and no more. All other content within the database wouldn't be returned, so the issue of overfetching wouldn't be a concern.
REST gets you the pizzas that the restaurant has on the menu, but GraphQL lets you modify that pizza to get exactly how much of what you want.
Opting for GraphQL against or with REST is a highly subjective decision, heavily influenced by the use-case. It is important not to consider GraphQL as an alternative to REST, nor as a replacement. To help simply those differences here’s a quick REST vs. GraphQL cheat sheet to refer to:
REST APIs | GraphQL APIs |
---|---|
Been around since 2000 | Been around since 2012 |
An architectural style largely viewed as a conventional standard for designing APIs | A query language for solving common problems when integrating APIs |
Uses a server-driven architecture | Uses a client-driven architecture |
Uses caching automatically | Lacks in-built caching mechanism |
Supports multiple API versions | No API versioning required |
Response output in JSON, but can also support YAML, HTML, and XML | Response output in JSON |
Doesn't offer type-safety or auto-generated documentation | Offers type-safety and auto-generated documentation |
Simplifying work with multiple endpoints requires expensive custom middleware | Allows for schema stitching and remote data fetching |
REST is good for simple data sources where resources are well defined. | GraphQL is good for large, complex, and interrelated data sources. |
REST returns data in a fixed structure defined by the server. | GraphQL returns data in a flexible structure defined by the client. |
With REST, the client must check if the returned data is valid. | With GraphQL, invalid requests are typically rejected by schema structure. This results in an autogenerated error message. |