GraphQL: A Deep Dive Into Benefits, Use Cases, and Strategies
In this deep dive into GraphQL, learn more about this tool that brings a paradigm shift in the way clients and servers interact.
Join the DZone community and get the full member experience.
Join For FreeThis is an article from DZone's 2022 Enterprise Application Integration Trend Report.
For more:
Read the Report
As the complexity of software applications grows, the number of interfaces among their various components also increases. This leads to an ever-growing API footprint and an explosion of integrations. Even minor changes start taking more and more time to implement, ultimately resulting in a maintenance nightmare. Refactoring your interfaces often appears to be the only solution, but refactoring is a costly business. It is usually not approved by the management unless there is a very strong reason to do so.
So what's the solution to this tricky problem?
GraphQL is a tool that brings a paradigm shift in the way clients and servers interact. While it is not a silver bullet by any means, it can act as a sweet spot between complete overhaul of the application and doing nothing at all.
What Is GraphQL?
GraphQL stands for Graph Query Language, but don't let those words mislead you. GraphQL is not like SQL. While it is a query language, we don't query typical database tables directly using GraphQL. GraphQL is more of a format or structure to define the contract between the client and the API server. Basically, you can think of GraphQL as a specification or a new API standard similar to REST.
However, it is often considered more efficient and flexible than REST. In fact, we can practically use GraphQL wherever we have used REST. In a way, GraphQL aims to do what REST was doing all these years, only better.
Note: GraphQL is a standard specification. As such, there is no official implementation. The closest we get are language-specific implementations of GraphQL specs available on the official GraphQL language support page.
Features of GraphQL
In this section, we are going to look at some of the key features of the GraphQL specification.
Declarative
In GraphQL, clients ask queries to the server. These queries are declarative in nature. See the below example of a typical query sent by a client:
{
book(id: "1") {
title
publishYear
}
}
The query is pretty self-explanatory. Basically, the client is asking for the book with id
of 1. Also, the client is specifying that it is only interested in the fields title
and publishYear
.
It is the job of the GraphQL server to make sure that only the fields specified within the query are returned as part of the response. The response could look like this:
{
"data": {
"book": {
"title": "The Way of Kings",
"publishYear": 2010
}
}
}
As you can see, this is a totally different approach from REST API design where a client has no control over what gets returned by the server.
Hierarchical
Queries in GraphQL are also hierarchical. For example:
{
book(id: "1") {
title
publishYear
authors {
name
}
}
}
Here, the client is asking for the Book with id
of 1. However, along with the book, the client is also interested in getting the author-related information of the book (specifically the name of the author). In GraphQL, queries can describe this type of hierarchical relationship quite easily.
Type Safety
Type safety is another important feature of GraphQL. In GraphQL, we have to declare schemas to specify our data models. A GraphQL schema helps the server determine whether the client's query is valid or not. These schemas are strongly typed.
type Book {
title: String!
publishYear: Int
price: Float
}
The type system can use primitive types such as numeric integers, Booleans, and strings. However, it can also refer to complex types such as objects.
GraphQL Core Concepts
There are a few core concepts in GraphQL that form the backbone of its query language. Let us look at the concepts one by one.
Schema Definition Language
As we saw in the previous section, GraphQL has a type system. It is used to define the schema. Basically, the syntax for writing the schema is also known as Schema Definition Language (SDL). Below is a simple schema for your reference:
type Author {
name: String!
}
This schema describes an Author
. It contains only one field, the name of the author. The !
mark denotes that name
is a mandatory field.
Queries
Queries are arguably the most important concept of GraphQL. Clients make queries to the GraphQL server. These queries specify the requirements of the client. If the query is found to be valid, the server sends a response. Below is an example of a typical GraphQL query where we specify the id
of the book and the specific fields we want to fetch:
{
book(id: "1") {
title
publishYear
}
}
Mutations
APIs are used not only to query information, but also to update information. In GraphQL, updates are supported using the concept of mutations. See below for an example of how the client sends a mutation to the GraphQL server:
mutation {
createAuthor(name: 'Robert Jordan', country: "USA") {
name
country
}
}
As you can see, the mutation syntax looks quite similar to the query. However, the mutation
keyword makes the GraphQL server aware that the client wants to perform an update or create operation.
GraphQL vs. REST
REST APIs are often inflexible and don't adapt well to changing client requirements. This is where GraphQL offers benefits when compared to the RESTful approach. To learn more about the differences, check out the article, "Choosing Between REST and GraphQL."
GraphQL Demo
We now have a pretty good idea about the features and concepts of GraphQL. Now is the time to see GraphQL in action. Let’s create a simple GraphQL API server. Basically, there are three things a GraphQL server needs to work properly:
- A web server
- A GraphQL schema with a resolver
- A request handler to process incoming requests
The simplest way to achieve the above requirements are as follows:
- For the web server part, we will use Express, a popular Node.js framework for building APIs.
- The schema and resolver are handled by the GraphQL package. This is a standard GraphQL implementation for JavaScript and forms the basis for other sophisticated implementations.
- Lastly, for the request handler, we will use the
express-graphql
package. This package is basically a middleware for Express.
In the first step, we will create a project directory and install the required packages.
Note that you need to have Node.js installed on your system:
$ mkdir graphql-express-demo
$ cd graphql-express-demo
$ npm init -y
$ npm install express express-graphql graphql --save
As discussed earlier, we install the express
, express-graphql
, and graphql
packages. Next, we create a file named server.js
and place the below code in that file:
var express = require('express');
var { graphqlHTTP } = require('express-graphql');
var { buildSchema } = require('graphql')
var schema = buildSchema(`
type Query {
hello: String
} `)
var root = {
hello: () => {
return "Hello, World"
},
}
var app = express();
app.use("/graphql", graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(4000);
console.log('GraphQL API server available at http://localhost:4000/graphql'
After the necessary import statements, we define the schema using the buildSchema()
function. Then, we specify the root
query and register one query type named hello
. Next, we set up the Express app and implement a request handler to handle incoming requests. Within the request handler, we configure the graphqlHTTP
middleware to use our schema and root query.
A typical GraphQL server usually has only one endpoint. All queries are processed by the same endpoint (unlike REST APIs, where each resource has its own endpoint). Here, that single endpoint is /graphql
. The graphiql
flag is set to the value true
. This flag enables the graphical user interface for our application, where you can play around with the queries and see the responses from the server. We can access the UI on http://localhost:4000/graphql.
GraphQL Pros and Cons
In this section, we will look at some pros and cons of GraphQL as a technology.
Pros:
- API clients get more freedom with GraphQL. The client applications can formulate queries depending on their needs in terms of required fields.
- Since GraphQL uses a Schema Definition Language based on type safety, it provides an automatic layer of validation. Developers consuming the GraphQL APIs can easily see what the schema supports and accordingly formulate the queries.
Cons:
- Since GraphQL supports hierarchical queries, complex queries with a lot of nesting can often lead to performance issues. To avoid these issues, we might have to implement rate-limiting or nesting limits to our GraphQL queries.
- While GraphQL is a great tool to reduce complexity, it might even be an overkill for small applications. For a simple application, a REST API might be a better option.
- GraphQL does not support HTTP web caching.
Conclusion
GraphQL is a wonderful tool to build APIs that are adaptable to evolving customer requirements. If your API footprint is growing out of hand and consumers are complaining about the need to call multiple endpoints to work with your application, it might be a good idea to explore GraphQL. If you are looking to build APIs without needing to constantly push out new versions while maintaining older versions, GraphQL is a great choice.
This is an article from DZone's 2022 Enterprise Application Integration Trend Report.
For more:
Read the Report
Opinions expressed by DZone contributors are their own.
Comments