Why GraphQL is redefining the way we design our APIs?
A better alternative to REST
Let’s look at the definition from the official website:
“GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.
GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.”
There are two key points to this definition:
- GraphQL is a “query language for APIs”.
- It “gives clients the power to ask for exactly what they need and nothing more”.
GraphQL is a new API standard that provides a more efficient, powerful and flexible alternative to REST.
As its core, GraphQL enables declarative data fetching were a client can specify exactly what data they need from an API. Instead of multiple endpoints that return fixed data structures, a GraphQL server only exposes a single endpoint and responds with precisely what the client asked for.
One of the great things about GraphQL besides its declarative data fetching capabilities is that it is programming-language agnostic. GraphQL is a strict specification, and there are libraries to help you implement GraphQL in many different languages. GraphQL isn’t tied to any specific database or storage engine and is instead backed by your existing code and data.
A more efficient alternative to REST
REST has been the most popular way to expose data from a server for at least the past decade. When the concept of REST was developed, applications were relatively simple and development pace wasn’t nearly where it is today. However, the API development landscape has radically changed over the last couple of years. There are three factors that are challenging the way we develop our APIs:
1. Increased mobile usage
With the increase of mobile usage and the different types of devices, like IoT devices or low-powered ones like Arduino consuming our APIs, there’s a need for more efficient ways to load our data. GraphQL minimizes the amount of data which is transferred across the network by being selective about the data depending on the client application’s needs. Thus, a mobile client can fetch less information, because it may not be needed on a small screen compared to the larger screen for the web application.
2. Variety of frontend frameworks and platforms
With the wide spectrum of front-end frameworks available, it becomes difficult to build and maintain one API that fits all our clients requirements. With GraphQL, each client can access the information it needs using one of the GraphQL clients, which can automatically handle batching, caching, and other features.
3. Fast development pace
Continuous deployment, rapid iterations and rapidly changing requirements have been the standard way of working for many companies. With REST APIs, the way data is exposed often needs to be changed to account for this fast development pace. This directly affects our velocity as a team to continuously deliver a valuable product to our clients.
GraphQL is not only for React Developers
The first ever app that used GraphQL is the Facebook mobile app. The team at Facebook came up with it as a result of writing an API for mobile apps. Interestingly though, GraphQL has mostly been picked up to be used for web applications and has gained little traction in the mobile development community.
One of the reasons behind this is the fact that Facebook always used to speak about GraphQL in the context of React, so it took sometime for non-React developers to understand that GraphQL was by no means a technology that was limited to only be used with React.
A rapidly growing community
GraphQL is currently being used in production by lots of different companies such as Facebook, Airbnb, Twitter, Netflix and Shopify, just to name a few.
There are entire conferences dedicated to GraphQL running every year such as GraphQL Conf, and great resources like How To GraphQL that will allow you to get started on your journey with this great technology.
GraphQL vs REST
Over the past decade, REST has become the de facto standard for APIs. It offers great ideas, such as stateless servers and structured access to our information. However, REST APIs have shown to be too inflexible to keep up with the rapidly changing requirements of the clients that access them.
REST is a strict specification but the concept has been widely misinterpreted. Many APIs claim to be “restful” APIs but they aren’t. The static nature of REST doesn’t go in hand with rapidly changing requirements.
GraphQL was developed to cope with the need for more flexibility and efficiency. It solves many of the shortcomings that us as developers face when interacting with REST APIs.
Enough talking. In order to show the major differences between REST and GraphQL when it comes to fetching data from an API, let’s consider an example scenario: we need to build a screen of a delivery app. This page needs to display the basic information of a restaurant, such as: name, address and food categories. The same screen should also include the different items of the menu and the different reviews the users left when ordering from this restaurant. How would this situation be solved with REST or with GraphQL?
Data Fetching with REST vs GraphQL
With a REST API, you would typically fetch data by accessing multiple endpoints. In the example, one of these could be
/restaurants/<id> endpoint to fetch the initial restaurant data. Secondly, we would need
/restaurants/<id>/products endpoint in order to get all the products for a given restaurant. Lastly, the
/restaurants/<id>/reviews endpoint that returns the list of reviews for a given restaurant.
With REST, you’d need to make three request to different endpoints in order to fetch the required data. You’re also over-fetching since these endpoints return additional information that’s not needed.
The problem: over or under-fetching
One of the most common problems is over or under-fetching. This happens because the only way for a client to get data is by hitting endpoints that return fixed data structures. It’s very difficult to design an API in a way that’s able to provide all clients with only the data they actually need.
Over-fetching means that the client downloads more information that is actually needed. In our case when we fetch the restaurant initial data we only want to show the name, address and categories but the endpoint exposes more information, e.g the date of creation or if the restaurant is accepting orders. That information is useless for the client because it doesn’t need display it.
Under-fetching and the n + 1 problem
Another issue is under-fetching and the n + 1 requests problem. Under-fetching generally means that a specific endpoint doesn’t provide the required information that the client needs. The client subsequently would need to make additional requests to fetch everything it needs. This can translate to a scenario in which a client needs to fetch a list of elements first, but then needs to make one additional request per element to fetch the required information.
As an example, consider the app we are building. If we want to show additional information for the reviews section of our screen, like the date of birth of the user that left the review, we would also need to hit the
/users/<id> endpoint of our API to get the date of birth of that user.
Common pattern with REST APIs
A common pattern with REST APIs is to structure the endpoints according to the screens of our app. This is handy since it allows the client to get all the required information for a particular screen by simply accessing the corresponding endpoint.
The major drawback of this approach is that it doesn’t allow for rapid product iterations. With every change that is made to the UI, there is a big risk that now we require more (or less) information than before. Consequently, the backend needs to be adjusted as well to account for the new data that we need. This kills productivity and notably slows down the ability to incorporate user feedback into a product.
With GraphQL, this problem is solved. Thanks to the flexible nature of GraphQL, changes on the client-side can be made without any extra work on the server. Since clients can specify the data they need, we don’t need to make adjustments in our backend when the data changes in the frontend.
Rewriting our API with GraphQL
With GraphQL, on the other hand, you’d simply send a single HTTP request to the GraphQL API that includes the specific data requirements. The API responds with a JSON object containing the requested information.
Using GraphQL the client can specify exactly the data it needs. Note that the structure of the server’s response follows the nested structure defined in the query.
Benefits of a Schema & Type System
GraphQL uses a strong type system to define the capabilities of an API. All the types that the API exposes are written down in a schema using the GraphQL Schema Definition Language (SDL). This schema serves as the contract between the client and the server in order to define how a client can access the data.
Once the schema is defined, the teams working on the frontend and backend can work independently. Frontend teams can easily test their applications by mocking the required data structures. Once the server is ready, the switch can be flipped for the client apps to load the data from the actual API.
The Schema Definition Language (SDL)
As we mentioned earlier, GraphQL has its own type ‘System’ that’s used to define a schema of an API. The syntax for writing schemas is called Schema Definition Language (SDL).
Here is an example of how can we use SDL to define a type called Restaurant:
This type has two fields, they’re called name and address and they are of type String. The exclamation mark following the type means that the field is required.
It’s possible to express relationships between types. For example in our delivery application, a Restaurant is associated with a list of Products, or we could also say that a Product belongs to a Restaurant:
Now, the other end of the relationship needs to be placed on the Restaurant type:
We just created a one-to-many relationship between Restaurant and Product since the products field on Restaurant is an array of products.
Fetching Data with Queries
The approach that’s taken in GraphQL is radically different than a traditional REST API. Instead of having multiple endpoints that return fixed data structures, GraphQL APIs typically only expose a single endpoint. That means that the client should specify to the server the data it needs. This information is called a query.
Let’s take a look at an example query that we could send to a server:
restaurants field in this query is called the root field of the query. Everything that follows the root field, is called the payload of the query. The only field that’s specified in this query’s payload is
This query would return a list of all restaurants currently stored in the database, along with the name. Here’s an example response:
Note that each restaurant only includes the name in the response, as the address is not returned by the server. That’s exactly because
name was the only field that was specified in the query.
If the client also needs the restaurant’s address, all it has to do is change the query and include the new field in the query’s payload.
One of the major advantages of GraphQL is that querying nested information is pretty easy. For example, if we want to load all restaurants with the name of its products, you could simply follow the structure of the defined types to request this information.
Queries with Arguments
In GraphQL, each field can have zero or more arguments. For example, the
restaurants field could have an
id parameter in order to return the specified restaurant with that id. Here’s how that query would look like:
Writing Data with Mutations
Most applications need some way to make changes to the data they handle. In a GraphQL API, this is achieved using mutations. Generally there are three kinds of mutations:
- Creating new data
- Updating existing data
- Deleting existing data
Mutation have the same syntax as queries, but they always need to start with the mutation keyword. Here’s an example for how we might create a new
Notice that this is very similar to the query we wrote before. The mutation also has a root field, in this case it’s called
createRestaurant. We also see the concept of arguments for fields, in this case the
createRestaurant field takes two arguments that specify the new restaurant’s
Like with a query, we’re able to specify a payload for mutation in which we can ask for different properties of the new Restaurant we created.
The server response for the above mutation would look as follows:
Realtime Updates with Subscriptions
Another requirement that many applications are likely to have is a realtime connection to the server in order to get realtime updates from certain events. For this situations, GraphQL offers the concept of subscriptions.
When a client subscribes to an event, it will hold a steady connection to the server. Whenever that event actually happens, the server pushes the corresponding data to the client. Unlike queries and mutations, subscriptions represent a stream of data sent over to the client.
Subscriptions are written using the same syntax as queries and mutations. Here’s an example where we subscribe to the event
After a client sends this subscription to the server, a connection is opened between them. Then, whenever a new mutation is executed and a new
Restaurant is created, the server sends the information about this restaurant over to the client:
Defining a Schema
Now that we have a basic understanding of what queries, mutations, and subscriptions are, let’s put it all together and learn how to write a schema.
The schema is one of the most important concepts while working with GraphQL APIs. It’s the specification of our API and defines how clients can request the data. It is often seen as a contract between the server and the client.
A schema is simply a collection of GraphQL types. However, when writing the schema for an API, there are some special root types:
Subscription types are the entry points for the requests sent by the client. To enable the
restaurants query we saw before, the
Query type should be written as follows:
restaurants is a root field of the API. Considering the example where we added the
id argument to the
restaurants field, we should write the
Query as follows:
As we see the
id argument is not required.
Similarly, for the
createRestaurant mutation, we should add a root field to the
Finally, for the subscriptions, we should add the
newRestaurant root field:
Putting it all together, this is the full schema for all the queries and mutations that we wrote earlier:
To conclude, GraphQL provides a number of benefits over traditional REST APIs, such as solving the problem of over or under-fetching typically associated with RESTful APIs.
However, developers must be comfortable with the additional complexity that GraphQL adds, in order to take advantage of this benefits.
Here at CreateThrive, we’re pretty excited about this tool as it increases developer productivity and is gaining more and more traction in the API ecosystem, so we’re happy to be promoting GraphQL’s widespread adoption.