The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.
As web and mobile applications become more mature and complex, software engineers invent clever new ways of improving the interaction between client and server within an application. One of the biggest paradigm shifts over the last few years in this regard has been GraphQL, an open-source query language and runtime for manipulating APIs. GraphQL was designed by Facebook in 2012 (and released publicly in 2015) to solve various weaknesses with traditional REST architecture by making a new system that is declarative, client-driven, and performant.
In this article, you will review what GraphQL is, familiarize yourself with important terminology and concepts of GraphQL, and discover how the GraphQL specification compares with the REST architectural style.
GraphQL stands for Graph Query Language, but unlike other query languages such as SQL (Structured Query Language), it is not a language for communicating directly with a database, but rather a language that defines a contract through which a client communicates with a API server. The GraphQL specification is an open standard that describes the rules and characteristics of the language. It also provides instructions for executing a GraphQL query.
Due to the fact that GraphQL is defined by an open standard, there is no official implementation of GraphQL. A GraphQL implementation can be written with any programming language, integrate with any type of database, and support any client (such as mobile or web applications), as long as it follows the rules outlined in the spec. One of the most popular commercial GraphQL implementations is Apollo GraphQL, which touts several GraphQL client and server implementations, but it is not necessary to use Apollo to use or understand GraphQL.
There are several key characteristics of GraphQL design. GraphQL queries are declarative and hierarchical, and a GraphQL schema is strongly-typed and introspective.
GraphQL queries are declarative, meaning the client will declare exactly which fields it is interested in, and the response will only include those properties.
This example GraphQL query for a hypothetical fantasy game API requests a wizard
with an ID of "1"
, and requests the name
and race
fields on that object.
{
wizard(id: "1") {
name
race
}
}
The response, which is returned in JSON format, will return a data
object that contains the found wizard
object, with the two fields the query requested.
{
"data": {
"wizard": {
"name": "Merlin",
"race": "HUMAN"
}
}
}
Since a GraphQL response only gives you the exact information you want, it results in a more efficient and performant network request than alternatives that always provide a complete set of data.
GraphQL queries are also hierarchical. The data returned follows the shape of the query. In this example, the query has been extended to include spells
, and is requesting the name
and attack
fields of every spell.
{
wizard(id: "1") {
name
spells {
name
attack
}
}
}
The response will now include an array of all the spell
objects associated with this particular wizard
. Although wizards
and spells
might be stored in separate database tables, they can be fetched with a single GraphQL request. (However, GraphQL is not opinionated about how the data itself is stored, so that is a presumption.)
{
"data": {
"wizard": {
"name": "Merlin",
"spells": [
{
"name": "Lightning Bolt",
"attack": 2
},
{
"name": "Ice Storm",
"attack": 2
},
{
"name": "Fireball",
"attack": 3
}
]
}
}
}
GraphQL is strongly-typed, as described by the GraphQL Type system. Types describe the capabilities of the values within a GraphQL server. The GraphQL types will be familiar to most programmers, with scalars (primitive values) like strings, booleans, and numeric integers, as well as more advanced values like objects.
This example creates a Spell
Object type with fields that correspond to String
and Int
scalar types.
type Spell {
name: String!
attack: Int
range: Int
}
A GraphQL schema is defined using the type system, which allows the server to determine whether or not a query is valid before attempting to query the data. GraphQL Validation ensures the request is syntactically correct, unambiguous, and mistake-free.
The Introspection feature allows GraphQL clients and tools to query the GraphQL server for the underlying schema’s shape and data. This allows for the creation of tools like GraphiQL, an in-browser IDE and playground for working with GraphQL queries, and other tools for automatically generating documentation.
For example, you can find out more about the Spell
type through this introspection feature via the __schema
.
{
__schema {
types {
name
kind
description
}
}
}
The response will also be JSON like any other GraphQL response:
{
"data": {
"__schema": {
"types": [
{
"name": "Spell",
"kind": "OBJECT",
"description": "A powerful spell that a wizard can read from a scroll."
}
]
}
}
}
The work of developing a GraphQL API happens on the backend, where the schema is defined and implemented. However, since all of the power of the GraphQL API is encompassed in a single endpoint on the server, it is up to the client via declarative queries to decide exactly what data it needs. This empowers developers to iterate quickly, as the front-end developer can continue to query the data the GraphQL API exposes without doing any additional backend work.
GraphQL exists in the application layer between client and data. The GraphQL server describes the capabilities exposed in the API, and the client describes the requirements of the request.
A GraphQL API is defined with a single endpoint, usually the /graphql
endpoint, which can access the full capabilities of the GraphQL server. Since GraphQL is an application layer technology and is transport agnostic, it can be served over any protocol, but it is most commonly served over HTTP.
A GraphQL server implementation can be written with any programming language, such as the express-graphql middleware which allows you to create a GraphQL API on a Node/Express HTTP server. GraphQL is also database agnostic, and the data for the application can be stored in MySQL, PostgreSQL, MongoDB, or any other database. The data can even be supplied by an aggregation of several traditional REST API endpoints. All that matters is that the data is defined in a GraphQL schema, which defines the API by describing the data available to be queried.
Requests made to a GraphQL server are called documents and consist of operations such as queries (for read requests) and mutations (for write requests).
Although there are advanced GraphQL clients, such as Apollo Client or Facebook’s Relay which provide mechanisms for caching as well as additional tools, no special client is required to make a request to a GraphQL server. A simple XMLHttpRequest
or fetch
from a web browser is sufficient for making requests by sending a GraphQL document to a GraphQL server.
Below is an example of a fetch
request to a /graphql
endpoint, which passes the GraphQL document as a string in the body of the POST
request.
async function fetchWizards() {
const response = await fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `{
wizards {
id
name
},
}`,
}),
})
const wizards = await response.json()
return wizards
}
fetchWizards()
This will return a JSON response for the request.
{
"data": {
"wizards": [
{ "id": "1", "name": "Merlin" },
{ "id": "2", "name": "Gandalf" }
]
}
}
GraphQL and REST are not interchangeable concepts, but they solve similar problems for applications. REST stands for Representational State Transfer, and is a software architectural style for sharing data between different systems. A RESTful API is an API that adheres to the principles and constraints of REST, which includes being stateless, cacheable, enforcing a separation of concerns between the client and server, and having a uniform interface, such as through URIs. GraphQL, as covered previously, is a specification for a query language and runtime for executing queries.
There are advantages and disadvantages to both systems, and both have their use in modern API development. However, GraphQL was developed to combat some perceived weaknesses with the REST system, and to create a more efficient, client-driven API.
Architecture - A REST API is typically defined by multiple endpoints on a server, but GraphQL exchanges data over a single endpoint. A GraphQL endpoint can return a complex graph of data that might require multiple REST queries, reducing the number of requests over the network for a single view.
Data fetching - A REST API returns the set of data that was determined on the server. This might be far too much data, such as if the view only requires one property from a response. It also might not be enough, such as a list endpoint that doesn’t return every property that a table requires in the view. GraphQL prevents this over and under fetching of data via declarative queries.
Error Handling - Since it is not necessary for GraphQL to be served over HTTP, there is no specification about using HTTP response codes for errors. Typically all GraphQL endpoints will resolve with a 200
HTTP code response, and failed results will include an errors
property alongside the data
property in the response. RESTful APIs, on the other hand, utilize different 400
level HTTP codes for client errors and 200
level HTTP codes for successful responses.
Versioning - GraphQL APIs strive to be backwards compatible and avoid breaking changes, contrasting with the common REST pattern of versioning endpoints, often with a /v1
or /v2
in the URL itself to determine the version. However, it is possible to implement your own versioning with GraphQL, or version via evolution with REST, it’s just less conventional.
Caching - Cacheability is an integral part of the REST guiding constraints. Since HTTP-based REST APIs consist of multiple endpoints using different HTTP methods, it can take advantage of existing HTTP conventions for caching and avoiding refetching resource. Since essentially every GraphQL request will be different but use the single endpoint, it cannot take advantage of any of the built-in HTTP caching mechanisms. GraphQL clients can take advantage of Global Object Identification to enable simple caching.
This list does not cover all the similarities and differences between REST and GraphQL, but summarizes many of the most critical points. Additionally, GraphQL can be used as a gateway that aggregates multiple REST endpoints or services, in which case both technologies can be used in harmony side-by-side.
Feature | GraphQL | REST |
---|---|---|
Description | GraphQL is a query language for APIs, and a server-side runtime | An architectural style for designing web services |
Data Fetching | A single HTTP endpoint that responds to deterministic queries | A set of HTTP endpoints that typically return a predetermined dataset |
Versioning | Versioning discouraged | Versioning common |
HTTP Status Codes | All responses, including errors, are typically 200 |
Implements HTTP Status codes |
Validation | Built-in metadata validation | Validation must be manually implemented |
Documentation | Built-in via type system and introspection | Not self-documenting, tools like OpenAPI available |
Caching | No | Yes |
Request Methods | Queries, mutations, and subscriptions (over POST for HTTP) |
All HTTP methods utilized (GET , POST , PATCH , PUT , DELETE , etc) |
Response Content-Type | JSON | Any (JSON, XML, HTML, etc.) |
GraphQL is an open-source query language and runtime for APIs. GraphQL was invented by developers at Facebook to solve various issues encountered with traditional REST APIs, such as over/under fetching data and inefficient network requests, by making a client-driven, declarative query language for APIs.
While GraphQL is not an interchangeable concept with REST, they both describe different ways to manage communication between a client and a server. In this article, you learned what GraphQL is, key differences and similarities between GraphQL and REST, and how a GraphQL server exposes data to a client.
This tutorial is part of our How To Manage Data with GraphQL series, which covers the basics of GraphQL.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
GraphQL is an open-source query language and runtime for manipulating APIs. GraphQL was designed by Facebook in 2012 (and released publicly in 2015) to solve various weaknesses with traditional REST architecture by making a new system that is declarative, client-driven, and performant.
This series covers the basics of GraphQL, beginning with important terminology and concepts. You’ll also create an Express API server in Node.js that serves up a GraphQL endpoint, giving you hands-on practice with building a schema and using operations (such as queries and mutations) and resolver functions.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.