GraphQL is a query language for APIs and a runtime environment for executing the queries. Originally launched by Facebook in 2012, graphql.org has been an open-source project and an alternative to RESTful Web Services since 2015.
GraphQL is primarily a flexible query language. This can also be seen on the oicial GraphQL website, where the title is “A query language for your API”. This hits the core of GraphQL quite well because the client-side data needs are in the foreground, i.e. the ability to query the required data for clients in a simple and flexible way.
An exciting point here is certainly the flexibility that the client gains. This can easily and precisely define which data (including relations) it needs from the server. GraphQL therefore enables a very client-oriented or use case-oriented view. With a request, the client can load exactly the data that it needs for a use case (no under fetching or over fetching).
When implementing an API of an existing web or mobile application, REST API is usually used. If we were to implement the API using the existing REST API, we had to create a new API at that time whenever we needed any functionality on the client-side.
For example, suppose your application has a model called Account and an endpoint called / accounts.
GET /accounts
{
"accounts": [
{
"id": "1",
"username": "john",
"email": "john.wick@q.agency",
"friends": [
"2",
"3"
],
"first_name": "John",
"last_name": "Wick"
},
{
"id": "2",
"username": "max",
"email": "max.payne@q.agency",
"friends": [
"1",
"4"
],
"first_name": "Max",
"last_name": "Payne"
}
]
}
If you want to get the information of an account with a specific id, you would do the following:
GET /accounts/1
{
"account": {
"id": "1",
"username": "john",
"email": "john.wick@q.agency",
"friends": [
"2",
"3"
],
"first_name": "John",
"last_name": "Wick"
}
}
If you look at the above data, the ids of your friends are put in the field called friends.
"friends": [
"2",
"3"
]
Following this list, if you want to get a list of your friends’ accounts, you need to create an API like this.
GET / accounts / 1 /? Include_friend_details = username, first_name
Or, you could do it like this
GET / accounts_with_friend_details / 1
If you proceed in this way, and if the size of the application increases later, there will really be many, many endpoints.
Of course, if the documentation is well made, maintenance will not be a major problem, but is there a simpler way?
If we make a query on the client-side and send it to the server as follows, wouldn’t it be nice to return the result as something like this?
Query
query {
account(id: "1") {
username
email
firstName
lastName
friends {
firstName
username
}
}
}
Result
{
"data": {
"account": {
"username": "john",
"email": "john.wick@q.agency",
"firstName": "John",
"lastName": "Wick",
"friends": [
{
"firstName": "Winston",
"username": "winston"
},
{
"firstName": "Marcus",
"username": "marcus"
}
]
}
}
}
Wouldn’t it be really cool if we made a query as neat as this and sent it to the server, and let the server take care of it and return the data in a given format?
You don’t have to worry about over fetching or under etching because only the necessary data is fetched through the query. What you just saw is GraphQL.
As you’ve seen, GraphQL embraces declarative data fetching with its queries. The client selects data along with its entities with fields across relationships in one query request. GraphQL decides which fields are needed for its UI, and it almost acts as UI-driven data fetching. There is no over fetching in GraphQL. A mobile client usually over fetches data when there is an identical API as the web client with a RESTful API. With GraphQL, the mobile client can choose a dierent set of fields, so it can fetch only the information needed for what’s on screen.
Schema Definition Language (SDL)
The GraphQL schema is the core of any GraphQL project. Nested in a GraphQL server, it defines every functionality available for the GraphQL client.
The most basic element of each schema is a type which allows:
- Establishing relations between dierent schema elements,
- Defining allowed GraphQL operations to be performed on the server and more.
To make it easier to understand the operation that a server can perform, GraphQL defines a universal schema syntax known as Schema Definition Language (SDL). The most basic elements of a GraphQL schema are object types. They represent an object you can fetch from your GraphQL server with available fields, i.e.:
type Book {
title: String
Author: Author
}
type Author {
name: String
books: [Book]
}
Query is a basic fetch operation in GraphQL to request data from the GraphQL server
type Query{
getBooks: [Book]
getAuthors: [Author]
}
Mutation is one of the basic GraphQL operations allowing you to manipulate the data (create, modify or delete):
type Mutation {
addBook(title: String, author: String) : Book
}
GraphQL vs REST
For REST services, the server decides which data is returned. With GraphQL, the client decides which data is desired and only returns what we asked. The diagram clearly defines which types can be queried and how they are structured.
REST example – several queries are necessary:
- query customers and get response from server
- query friends and get a response from the server
- query family and get response from server
GraphQL example – one query is enough.
Now here is the real deal: GraphQL was created to make smart queries by requesting the exact data you need. This is in direct contrast to REST, where you are compelled to accept any data that is handed over to you. The benefits of using GraphQL for queries are listed below:
- Able to request all types of data.
- Can obtain cumulative data from multiple sources.
- Can request selective and specific data from an API’s endpoint.
GraphQL and REST
Let’s say you have developed an app that still relies on RESTful Web Services. How diicult would it be to convert to GraphQL – is it even practical?
I believe that RESTful Web Services and GraphQL can complement each other well. GraphQL can be used as a gateway to give the client a unified view of the data. The GraphQL gateway would then not load the data itself (e.g. from a database), but call the existing REST endpoints and act as an aggregation point.
This would provide a client with the flexibility of GraphQL and still leave the actual services as RESTful services. This procedure can be particularly useful for microservice architectures.
With a new project, you can of course consider using GraphQL alone. In this case, I would make the decision based on the specific problem. Solving every problem with GraphQL blindly is not the right approach.
GraphQL is (not) a replacement for REST
GraphQL isn’t perfect. For example, modeling your data in a graph structure is a natural fit if you’re already storing it as a graph, as Facebook does, but much less so if you’re storing it in a table. That’s not to say GraphQL can’t be used by relational systems – it can – but it may take some additional work. However, GraphQL oers some clear advantages over REST, and in fact, we have only highlighted the most significant ones here.
GraphQL APIs can be an exciting new technology, but it’s important to understand the tradeos before making such architectural decisions. Some APIs such as those with very few entities and relationships across entities like analytics APIs may not be suited for GraphQL. Whereas applications with many dierent domain objects like e-commerce where you have items, users, orders, payments, and so on may be able to leverage GraphQL much more.