APIs are a fundamental component of software development, allowing different systems and applications to interact and share data. The various tools, standards, and protocols for building and using APIs are called API technologies. They can include protocol specifications or architectures, security protocols, and data formats such as JSON or XML.
Representational State Transfer (REST) is often considered the gold standard protocol for API architecture. However, a popular new alternative has emerged, known as GraphQL, which contains several unique features that REST doesn’t have. These include allowing clients to request only the specific data they need and query multiple resources in a single request.
Choosing between REST and GraphQL often depends on the specific requirements of your project. While REST is great for simple, well-documented APIs, GraphQL is better suited for complex, evolving APIs.
In this article, we’ll delve into the fundamental principles of both REST and GraphQL and compare their advantages and disadvantages to help you determine when to use each one.
Let’s begin by exploring some important topics when working within the REST (or RESTful) architecture.
What are REST APIs used for?
REST APIs are used to enable communication and data exchange between different software systems and applications. REST APIs provide a standard way for applications to communicate over the internet using HTTP protocols. REST provides a set of guidelines for developing web services known as the REST architectural principles. These include:
- The use of a stateless protocol (usually HTTP)
- The use of resource-based Uniform Resource Identifiers (URIs)
- The use of standard HTTP methods such as GET, POST, PUT, and DELETE
In a REST architecture, each resource is identified by a unique URI and can be accessed using the standard HTTP methods.
REST was first introduced by Roy Fielding in 2000 as part of his PhD dissertation and quickly became popular due to its simple and flexible nature. It also leveraged the existing web infrastructure, making it easy to interact with using standard HTTP client libraries.
REST APIs are used to build various types of web applications, such as e-commerce platforms, social media networks, content management systems, and mobile applications. They enable developers to create APIs that are platform-independent, making it possible to integrate applications built using different programming languages and technologies.
Some common use cases of REST APIs include retrieving data from a remote server, updating data on the server, creating new data, and deleting data from the server. REST APIs are often used to power the backend of modern web applications, enabling them to communicate with client-side frameworks and libraries like React, Angular, or Vue.
Overall, REST APIs play a crucial role in modern software development, enabling applications to communicate and share data seamlessly, providing the foundation for building scalable and extensible web applications. They do come with challenges which we'll cover in the next section.
REST API challenges
Some common challenges when working with REST APIs include the potential for over-fetching or under-fetching of data which can cause additional load on the server and client side. In the following sections, we’ll explore these two issues in more detail.
Over-fetching occurs when a client receives unnecessary data beyond the specific subset they requested, which can cause issues on both the server and client side because the server returns data that isn’t being used and the client receives data that isn’t needed.
To demonstrate how over-fetching can occur, let’s look at an example.
Say you’re building the user profile page for a client application, and you only have the /users/:id endpoint available to fetch user information. You only need the user’s name and address. To fetch this information, you’d most likely make an HTTP GET request like this:
The server would then return the information in the body of the response, typically in JSON or XML format:
While this response provides you with the name and address you need for your task, it also includes additional data such as age, email, phone, occupation, status, and created_at.
Over-fetching becomes a more recognizable issue with larger applications, where it occurs multiple times on a much bigger scale. Wasting resources on processing large quantities of unnecessary data can have a significant impact on a client application’s performance.
In contrast, under-fetching involves making numerous additional requests to the server to retrieve necessary data. This is a situation where an API endpoint does not provide enough data to fulfill a client's request, resulting in the client needing to make additional requests. This can lead to increased network usage, additional latency, and decreased performance. For example, if an API endpoint is designed to return a single user's name and email, but the client also needs the user's address, another API request will be required to retrieve that information.
Returning to the earlier example, let’s assume that on top of needing the user’s name and address, you also need a list of their friends' information. You still have the /user/:id endpoint available, but it’s now improved to only return the following:
The friends field contains a list of user IDs marked as friends of the user in the original payload. Returning the list of IDs in a field rather than a list of objects can reduce the amount of data sent across the network. However, because you need the names and addresses of each friend, you now need to make the following separate requests to obtain this information:
Both over-fetching and under-fetching can lead to performance issues and unnecessary network usage, making it important to carefully design API endpoints to provide the necessary data without returning excessive or insufficient data. One way to address these issues is by using GraphQL, which enables clients to request only the data they need and avoid over-fetching or under-fetching.
What is GraphQL used for?
GraphQL is a query language for building flexible, efficient, and powerful APIs. It was first developed by Facebook in 2012, then later open-sourced in 2015, and has since gained significant traction in the developer community.
In GraphQL, the client defines the structure of the necessary data by making a request using the GraphQL query language. These requests consist of a series of fields that define the shape of the requested data, each containing its own set of subfields. The server then responds to the request with a JSON object that matches the shape of the query.
By allowing clients to express their data requirements through a single endpoint rather than a fixed set of endpoints, GraphQL avoids the possibility of both over-fetching and under-fetching.
In the following sections, we’ll discuss a few other core concepts behind GraphQL.
In GraphQL, you use queries to fetch data from the server. They allow you to specify the data you need and are typically used for read-only operations.
Here’s an example of how you might use a GraphQL query to request a specific user object:
This query requests the id, name, and address fields of a user object and specifies that the id of the requested user is 1.
Recall the earlier example of requesting a list of friends for a certain user, along with their names and addresses. Using GraphQL, you can request the specific information you’re looking for under each friend object being queried:
With queries, you can now easily retrieve all the information you need in a single request rather than making multiple requests spread out over multiple endpoints, as with a REST API.
You can use mutations to make changes to the server data, typically for create, update, and delete operations. Here’s an example of how you might use a GraphQL mutation to create a new user object:
The mutation creates a new user object with the provided name and address and requests the id, name, and address fields of the created user object.
On the server side, GraphQL architecture usually consists of two main elements:
The schema defines the types of available data in the system, with the relationships between them typically written in the GraphQL Schema Definition Language (SDL). It also defines the data structure the server can provide, as well as the structure of queries and mutations you can make to access that data.
Resolvers are server functions that handle the execution of a GraphQL query. They’re responsible for fetching data for their corresponding fields.
On the client side, you can use a GraphQL client library to interact with the GraphQL server. A GraphQL client library simplifies the process of making GraphQL requests and parsing the responses.
When to use REST versus GraphQL
Now that you know the difference between REST and GraphQL, let’s explore some use cases where you may choose one over the other.
When to choose REST
REST is easy to understand, which makes it a great option when building simple APIs and applications that only require basic create, read, update, and delete (CRUD) operations. If the API doesn’t require complex queries, the specificity of GraphQL won’t be necessary.
REST is often a better solution where performance is a concern. REST APIs tend to have a simpler and more predictable data structure, which allows the server to return the data faster. In this case, making multiple requests is beneficial, as smaller chunks of data are easier to handle and process. Meanwhile, sending complex queries using GraphQL can slow down the server response time.
When to choose GraphQL
GraphQL is a highly flexible option that’s better suited for building APIs that require complex data fetching and manipulation. It deftly avoids over-fetching and under-fetching data, leading to lower bandwidth usage and faster response times.
Additionally, GraphQL is better at building APIs that require data from multiple sources. Whereas REST APIs would need to make multiple HTTP requests, GraphQL allows clients to send a single query to retrieve data from multiple sources as a single JSON object.
Another advantage of using GraphQL is that you don't need to change your requests or modify the endpoint when the data models or services on the server side change. You can continue to receive the same data fields in the same format, allowing for a better alignment between your data and server data and an improved developer experience.
So, which should you use?
Ultimately, both technologies are popular for a reason.
- Use GraphQL when dealing with complex, evolving APIs with varying data requirements, as it allows clients to request only the data they need and query multiple resources in a single request.
- Use GraphQL when needing real-time updates and fine-grained control over data fetching, whereas REST APIs are better suited for one-time or batch data processing.
- Use REST when working with simple, well-documented APIs, where data requirements are relatively fixed and straightforward.
- Consider the trade-offs between flexibility and performance, as GraphQL provides more flexibility but can result in higher network usage and performance overhead, while REST APIs are more performant but less flexible.
GraphQL is a highly flexible query language that can express complex data requirements easily and in more detail than a traditional REST API. However, if the API you’re building only requires basic CRUD operations and simple queries, a REST API can be a more straightforward and efficient solution.
The best choice depends on the specific needs and goals of your project.
Using Airplane to send REST requests and connect to GraphQL APIs
Airplane is a developer platform for building UIs and workflows. Using Airplane, you can transform scripts, queries, and APIs into sharable applications.
Airplane makes it easy to connect to GraphQL APIs and send REST requests. With REST Tasks in Airplane, you can build/use existing APIs and have Airplane act as an interface to them.
You can read more in the REST Tasks docs and GraphQL Tasks docs. You can also sign up for Airplane for free to try it out!
Check out the Airplane blog for more tutorials such as how to make and schedule API requests in three steps and how to build an admin panel using React JS in under 15 minutes.