We will introduct GraphQL in this article and compare it with REST API.
Have you ever worked on Web app development project before? If so, then you may have already encountered the term "GraphQL". But what exactly does it mean? Is it used in server-side or client-side configurations? Additionally, when is GraphQL integration preferable to other alternatives? In this article, we will guide you through these questions.
As a communication channel for data transfer between software components over the internet, APIs play an indispensable role in modern web service architectures, acting like oxygen. API technologies such as SOAP (a web services messaging protocol), REST (architectural style), and GraphQL (a query language and tool) facilitate software development by supporting integration and data exchange between different services, making development more convenient and flexible.
Despite the numerous types of APIs, debates in recent years have predominantly centered on two main paradigms: REST (representational state transfer) and GraphQL. Both offer a range of advantages and are used globally in web projects. However, they differ significantly in how they manage data communication.
What is REST API?
REST is a structured architecture style developed in the early 20th century for building cross-network hypermedia applications, intended to adopt a stateless client/server cacheable communication protocol. REST API (also known as RESTful API) is the driver of the REST architecture.
REST API uses Uniform Resource Identifiers (URI) to address resources. REST API works by using different endpoints to perform CRUD (create, read, update, and delete) operations on network resources. They rely on predefined data formats (known as media types or MIME types) to determine the form and size of the resources they provide to clients. The most common formats are JSON and XML (sometimes HTML or plain text).
After the client requests a resource, the server processes the query and returns all data related to that resource. The response contains HTTP response codes such as "200 OK" (for a successful REST request) and "404 Not Found" (for a non-existent resource).
What is GraphQL?
GraphQL is both an API type (or query language) and a runtime engine for responding to those queries. It offers a simplified API and is particularly suited for mobile applications and the implementation of complex architectures that require specific data subsets.
With GraphQL, developers can specify the data they want to retrieve from the API. It also allows for on-demand data retrieval instead of fetching everything at once, applies changes immediately, and integrates third-party data sources into the application.
Applications can use GraphQL queries to call GraphQL services. These queries return the exact data elements requested by the client. This saves multiple API calls, network bandwidth, and post-processing. It is a highly efficient solution for data-centric APIs that are located close to consumer devices such as tablets and mobile phones.
How does GraphQL work?
Each GraphQL service defines a set of types to describe the possible data you can query in that service (i.e., schema). Then, when queries and mutations (the types of operations supported by GraphQL) arrive, they are validated and executed based on that schema and processed using resolvers.
Therefore, a complete GraphQL implementation must have two parts: schema and resolvers.
GraphQL operations
The operations supported by GraphQL include:
- Query: Used to READ data
- Mutation: Used to WRITE data, including operations to add, modify, and delete data
- Subscription: Used to request a persistent connection for data, allowing the client to declare the types of events it is interested in and the data that should be returned Queries and mutations rely on on-demand HTTP connections; subscriptions rely on long-lived connections such as WebSocket.
GraphQL schema
Schemas define the types of data and their fields that can be retrieved through GraphQL queries:
type OrganizationRole {
id: ID!
scopes: [String]
}
type Organization {
id: ID!
name: String!
roles: [OrganizationRole]
}
type Role {
id: ID!
name: String!
description: String
scopes: [String]
}
type User {
id: ID!
username: String
primaryEmail: String
roles: [Role]
organizations: [Organization]
}
type Query {
users: [User]
}
Let's take Logto as an example. When validating permissions on developers business APIs, we often need to know the Role and Organization corresponding to the current user (as well as the related OrganizationRole) in order to understand what kind of permissions the user has and to decide whether to allow the user to execute the corresponding operation.
GraphQL resolver
A resolver is a function that can retrieve the data for some fields in GraphQL queries. At runtime, the GraphQL query engine will compare each query against the schema to verify if the query is valid. If the query is valid, the query engine will run the resolver for each field to fetch the data for that field.
Differences between GraphQL and REST APIs
GraphQL and REST APIs are tools for exchanging data between different web services, but due to their different approaches to solving problems, there are many differences between them.
Flexibility
The implementation of REST API is with finer granularity, and GraphQL can obtain various forms of data through a single API, whereas each individual REST API may only fetch a very limited portion of the data.
Referring to the previous example, we can get all relevant data including user, role, and organization in one go through a single GraphQL API. However, if using REST API, in most cases, we may need to first call the GET /users/:id
API to get the user data, use GET /users/:userId/roles
to get the role information related to the user, and use GET /users/:userId/organizations
to get the organization data related of the user.
This is not the worst case. After obtaining the data related to the user's role, we may also need to request the GET /roles/:roleId
API to get the details related to the role. These APIs all depend on the return results of the previous API calls, which in some degree may limit the system's performance.
On the other hand, the design of the REST API can limit the function of each API to a very small scope, making it more convenient to call and maintain in engineering practice. While GraphQL provides great flexibility, it also brings some additional workload for usage and maintenance.
Data retrieval
When using GraphQL to fetch data, we can get appropriate data through writing suitable queries without the issues of under- and over-fetching.
However, due to the general design of REST API, we often need to call multiple different REST APIs to get exactly the data we need, as we exemplified in the previous section. The fetched data may also have an over-fetching issue since we cannot set precise filtering conditions in the API, which requires post-processing of the data fetched by the REST API.
Caching
The REST API has a mature ecosystem, and developers can also use various caching technologies such as server-side or network layer (like CDN) to help improve API performance.
However, due to its flexibility, many of the caching technologies available for the REST API are not applicable to GraphQL. It is necessary to handle caching on the client-side, based on specific use cases, which brings extra workload to client development.
There are many other differences between GraphQL and REST API as well. For instance, GraphQL cannot upload files, but the REST API can. Due to the limited space in this article, we can't list all of them, but with the development of time, these limitations might be resolved in the near future.
Which one should I use? GraphQL or REST APIs?
There are some situations where GraphQL is a better practice compared to REST API:
- When client-side requirements change frequently In this case, using GraphQL can save a lot of development time on the server side, otherwise, it would take a lot of time to repeatedly modify the API implementation.
- When the client side is sensitive to network latency In such cases, multiple network requests and dependencies between requests can lead to a very poor user experience on the client side, and using fewer requests to achieve the same data acquisition goals becomes necessary. GraphQL is a better choice compared to REST API in this situation. Of course, if there are enough resources, more task-specific REST APIs can also be developed for such use cases.
Conclusion
Although GraphQL has gained strong momentum as a newcomer in recent years, REST API still holds significant importance for a long time due to its atomic design and rigor.
By using REST API, the form of input and output for a single API can be strictly restricted, with many special limitations added in the implementation of the API. It is also easy to learn and get started. With comprehensive API documentation, users can easily find the APIs they need to build systems that meet their requirements.