Table Of Contents
In this article, you will learn what GraphQL is and why it is getting so much attention from developers and discuss how it differs from REST by exploring the different concepts, design principles, pros and cons of GraphQL.
Introduction
GraphQL (Graph Query Language) is not a database query language like SQL (Structured Query Language) but an approach to client-server communication. It is a query language for your APIs and runtime for executing queries. It isn't tied to any specific database, technology or language and, is instead backed by your existing code and data. It prioritizes giving clients only the data they request. It was developed at Facebook to make APIs fast, flexible, and developer-friendly.
GraphQL is transport agnostic but is typically served over HTTP.
The GraphQL specification describes the capabilities and characteristics of the language and serves as a guideline for all the implementation of GraphQL. When the spec was released, the creators of GraphQL also shared a reference implementation of the GraphQL specification (graphql-js), designed for running GraphQL in a Node.js environment. The goal of this reference implementation is not to mandate which language you use to implement your service. A GraphQL implementation can be written with any programming language, and integrated with any type of database, as long as it follows the spec. Some of the open-source implementation of GraphQL written in various languages are listed in this website.
GraphQL Server
A GraphQL server is a server-side implementation of the GraphQL spec. It is language and transport agnostic which means that it can be implemented with any programming language and can be served over any protocol. GraphQL servers are composed of two main parts: Schema
and Resolvers
. GraphQL Schema defines the shape of the data or API and GraphQL Resolver is function that populates every field in the schema so that GraphQl Server can respond to the requests for that data.
Example:
-
GraphQL Schema
type User { id: ID! name: String } type Query { user(id: ID!): User users: [User] }
-
GraphQL Resolver Function
const resolvers = { Query: { user(parent, args, context, info) { return db.users.find((user) => user.id === args.id) }, users() { return db.users }, }, }
GraphQL Client
GraphQL Client is basically a code that makes a request (with queries or mutations) to GraphqQL server. There are many powerful GraphQL Clients like Apollo GraphQL
and Relay
which handle batching and catching. But those clients are not needed just to make a request to the GraphQL Server. A simple curl
command or fetch
api is sufficient to make a request.
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ name }"}' \
http://localhost:4000/graphql
const name = await fetch("/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ query: `{ name }` }),
}).then((response) => response.json())
Design principles
-
Hierarchical
GraphQL queries are hierarchical. Fields are nested within other fields and the data returned follows the shape of the query.
Let's take an example by querying info about a user.
-
Here the following query is asking for the fullname, age and blogs (title and slug fields only) fields of a user with id "01".
{ user(id: "01") { fullName age blogs { title slug } } }
-
Here the response follows the shape of the query and returns fullname, age and blogs (title and slug only) associated with the user of id "01".
{ "data": { "user": { "fullName": "Shrek", "age": 80, "blogs": [ { "title": "How to pet dog", "slug": "/hot-to-pet-dog" }, { "title": "How to pet cat", "slug": "/hot-to-pet-cat" } ] } } }
-
-
Strongly typed
A GraphQL server is backed by the GraphQL Type System. The type system is used to determine if a query is valid. The type system also describes the input types of query variables to determine if values provided at runtime are valid. It can be ensured that the given query is both syntactically correct and valid within the GraphQL type system at development time.
type User { id: String! fullName: String! age: Int! blogs: [Blog] }
Above example creates
User
Object type with fieldsfullName
asString
,age
asInt
andblogs
as array ofBlog
. -
Introspective
A GraphQL server supports introspection over its schema. Introspection is the ability to query which resources are available in the current API schema. GraphQL Client can query the type system using the GraphQL syntax itself.
Let's take an example of an app which has a User Object type as.
type User { id: String name: String }
-
The following query can be used to find more about
User
type.{ __type(name: "User") { name fields { name type { name } } } }
-
Reponse:
{ "__type": { "name": "User", "fields": [ { "name": "id", "type": { "name": "String" } }, { "name": "name", "type": { "name": "String" } } ] } }
-
-
Product-centric
GraphQL is unapologetically driven by the requirements of views and the front-end engineers that write them. We start with their way of thinking and requirements and build the language and runtime necessary to enable that.
-
Client-specified response
A GraphQL response contains exactly what a client asks for and no more. In GraphQL, the specification for queries are encoded in the client rather than the server. Client is responsible for specifying how it will comsume the capabilities published by a GraphQL service.
Why use GraphQL ?
-
No over-fetching
With RESTful APIs, you need to fetch the complete response just to use some fields from the response. But a GraphQL response contains exactly what a client asks for and no more.
Suppose you are building an app and you need just the
title
andslug
of all the blogs you have written. With RESTful APIs, you have to fetch all the info about all of those blogs. But GraphQL lets you specify exact fields and types to fetch.Response examples:
-
No multiple roundtrips
With RESTful APIs, you need multiple requests to fetch related or hierarchical data. You send request to the server, the server returns the id and then you use that id to send another request to the server. But with GraphQL, you can use nested queries to fetch such related data in a single request.
Suppose in your blog app you need the
name
andemail
of the author of a blog with specificid
. With RESTful APIs, you have to first fetch theblog
resource (which has the author id) and then fetch theuser
resource using that author id. But with GraphQL, you can specify you also want to fetch thename
andemail
of the author.Response examples:
-
Versioning is not required
In REST architecture, new versions
(/v1, /v2, /v3)
need to be created as APIs evolve and structure of response changes. This leads to confusions and challenges down the line. In GraphQL, there is no need to maintain versions. You can just add the new fields and deprecate the old fields in the GraphQL Schema.type ExampleType { oldField: String @deprecated(reason: "Use `newField`.") newField: String }
-
Better performance
As discussed above, GraphQL reduces the size of the response by allowing us to specify required fields and minimizes the roundtrips to the server by allowing us to use nested queries. This helps save bandwidth and improve the performance of client-side applications.
-
GraphQL vs REST
REST (Representational State Transfer) is a software architectural style for designing stateless web APIs whereas GraphQL (Graph Query Language) is a query language and a server-side runtime for executing queries.
Basis | GraphQL | REST |
---|---|---|
Description | A query language for APIs and a server-side runtime | An architectural style for designing APIs |
Caching | No HTTP Caching | Supports HTTP Caching |
Versioning | Versioning is discouraged | Versioning is common |
HTTP Methods | Only POST ( sometimes GET ) is used |
All HTTP methods are used |
HTTP Status Codes | Always returns an HTTP Status code of 200 (even on error) | Returns different HTTP Status codes based on type and completion of request |
Validation | Built-in validation | No Built-in validation |
Documentation | Self documenting | No self documenting |
Shape of Response | Determined by client | Determined by server |