Codementor Events

How I learned GraphQL is the better REST

Published Jun 26, 2018Last updated Dec 23, 2018
How I learned GraphQL is the better REST

About me

Hi. I'm Joel, a visionary who has learned to wield technology for the betterment of our collective ideas. I like to travel, explore, adventure, hike, climb, write, build, share, and learn how to get the best ideas to market. I'm a blend of visionary, integrator, and marketer whose true direction is North. I ride the wave of full stack architect and full stack marketer on the daily ... finding the best ways to get us from here to where we know we want to be.

Why I wanted to learn GraphQL

I have always been known to and for being on the bleeding edge of advancement, either in technology, philosophy, or elsewhere... it's an essential gift of being a visionary. So for someone who starts a lot of new projects on stacks that become growing businesses that need to scale the entire toolchain, including the methods of securing and transporting data between endpoints of any type (IoT, mobile, web, API, chat, bot, etc); and also knowing that real time communication is a request often made by app owners and product designers; I set out to listen to what the vision community of technology futurists were saying and what I heard was this over and over; REST is DEAD.

Well - yes, it should be. It can be rather difficult to secure, optimize, and tune to efficiency at scale (especially at the developer experience), which most applications end up requiring beyond the two year mark. All software bloats, and I need a way to give app developers a better workflow to building future proof stacks for their business, so they can continue to focus on the thing that truly matters most: creating value for customers and/or users.

Enter GraphQL - where building serverless, API driven full stack applications is like making pancakes - mix, heat, and eat - with no mess.

GraphQL is a new API standard that provides a more efficient, powerful and flexible alternative to REST. It was developed and open-sourced by Facebook and is now maintained by a large community of companies and individuals from all over the world.

APIs have become ubiquitous components of software infrastructures. In short, an API defines how a client can load data from a server.

At its core, GraphQL enables declarative data fetching where a client can specify exactly what data it needs from an API. Instead of multiple endpoints that return fixed data structures, a GraphQL server only exposes a single endpoint and responds with precisely the data a client asked for.

GraphQL - A Query Language for APIs

Most applications today have the need to fetch data from a server where that data is stored in a database. It’s the responsibility of the API to provide an interface to the stored data that fits an application’s needs.

GraphQL is often confused with being a database technology. This is a misconception, GraphQL is a query language for APIs - not databases. In that sense it's database agnostic and effectively can be used in any context where an API is used.

A more efficient Alternative to REST

💡 Learn more about the top reasons to use GraphQL in this blog post.

REST has been a popular way to expose data from a server. When the concept of REST was developed, client applications were relatively simple and the development pace wasn’t nearly where it is today. REST thus was a good fit for many applications. However, the API landscape has radically changed over the last couple of years. In particular, there are three factors that have been challenging the way APIs are designed:

1. Increased mobile usage creates need for efficient data loading

Increased mobile usage, low-powered devices and sloppy networks were the initial reasons why Facebook developed GraphQL. GraphQL minimizes the amount of data that needs to be transferred over the network and thus majorly improves applications operating under these conditions.

2. Variety of different frontend frameworks and platforms

The heterogeneous landscape of frontend frameworks and platforms that run client applications makes it difficult to build and maintain one API that would fit the requirements of all. With GraphQL, each client can access precisely the data it needs.

3. Fast development & expectation for rapid feature development

Continuous deployment has become a standard for many companies, rapid iterations and frequent product updates are indispensable. With REST APIs, the way data is exposed by the server often needs to be modified to account for specific requirements and design changes on the client-side. This hinders fast development practices and product iterations.

History, Context & Adoption

GraphQL is not only for React Developers

Facebook started using GraphQL in 2012 in their native mobile apps. Interestingly though, GraphQL has mostly been picked up to be used in the context of web technologies and has gained only little traction in the native mobile space.

The first time Facebook publicly spoke about GraphQL was at React.js Conf 2015 and shortly after announced their plans to open source it. Because Facebook always used to speak about GraphQL in the context of React, it took a while for non-React developers to understand that GraphQL was by no means a technology that was limited to usage with React.


Dan Schafer & Jing Chen publicly introduce GraphQL React.JS Conf 2015. Watch video.

A rapidly growing Community

In fact, GraphQL is a technology that can be used everywhere a client communicates with an API. Interestingly, other companies like Netflix or Coursera were working on comparable ideas to make API interactions more efficient. Coursera envisioned a similar technology to let a client specify its data requirements and Netflix even open-sourced their solution called Falcor. After GraphQL was open-sourced, Coursera completely cancelled their own efforts and hopped on the GraphQL train.

Today, GraphQL is used in production by lots of different companies such as GitHub, Twitter, Yelp and Shopify - just to name only a few.


Despite being such a young technology, GraphQL has already been widely adopted. Learn who else is using GraphQL in production.

There are entire conferences dedicated to GraphQL such as GraphQL Summit or GraphQL Europe and more resources like the GraphQL Radio podcast and GraphQL Weekly newsletter.

How I approached learning GraphQL

Over the past decade, REST has become the standard (yet a fuzzy one) for designing web APIs. It offers some great ideas, such as stateless servers and structured access to resources. However, REST APIs have shown to be too inflexible to keep up with the rapidly changing requirements of the clients that access them.

GraphQL was developed to cope with the need for more flexibility and efficiency! It solves many of the shortcomings and inefficiencies that developers experience when interacting with REST APIs.

To illustrate the major differences between REST and GraphQL when it comes to fetching data from an API, let's consider a simple but typical scenario:

A content application which needs to display the titles of posts of a specific user

The same screen also displays the names of the last 3 followers of that user. How would that situation be solved with REST and GraphQL?

Data Fetching with REST vs GraphQL

With a REST API, we would typically gather the data by accessing multiple endpoints. In the example, these could be /users/<id> endpoint to fetch the initial user data. Secondly, there's likely to be a /users/<id>/posts endpoint that returns all the posts for a user. The third endpoint will then be the /users/<id>/followers that returns a list of followers per user.


With REST, we have to make three requests to different endpoints to fetch the required data. We're also overfetching since the endpoints return additional information that's not needed.

In GraphQL on the other hand, we'd simply send a single query to the GraphQL server that includes the concrete data requirements. The server then responds with a JSON object where these requirements are fulfilled.


Using GraphQL, the client can specify exactly the data it needs in a query. Notice that the structure of the server's response follows precisely the nested structure defined in the query.

No more Over- and Underfetching

One of the most common problems with REST is that of over- and underfetching. This happens because the only way for a client to download data is by hitting endpoints that return fixed data structures. It's very difficult to design the API in a way that it's able to provide clients with their exact data needs.

"Think in graphs, not endpoints." Lessons From 4 Years of GraphQL by Lee Byron, GraphQL Co-Inventor.

Overfetching: Downloading superfluous data

Overfetching means that a client downloads more information than is actually required in the app. Imagine for example a screen that needs to display a list of users only with their names. In a REST API, this app would usually hit the /users endpoint and receive a JSON array with user data. This response however might contain more info about the users that are returned, e.g. their birthdays or addresses - information that is useless for the client because it only needs to display the users' names.

Underfetching and the n+1 problem

Another issue is underfetching and the n+1-requests problem. Underfetching generally means that a specific endpoint doesn’t provide enough of the required information. The client will have to make additional requests to fetch everything it needs. This can escalate to a situation where a client needs to first download a list of elements, but then needs to make one additional request per element to fetch the required data.

As an example, consider the same app would also need to display the last three followers per user. The API provides the additional endpoint /users/<user-id>/followers. In order to be able to display the required information, the app will have to make one request to the /users endpoint and then hit the /users/<user-id>/followers endpoint for each user.

Rapid Product Iterations on the Frontend

A common pattern with REST APIs is to structure the endpoints according to the views that we have inside our app. This is handy since it allows for the client to get all required information for a particular view by simply accessing the corresponding endpoint.

The major drawback of this approach is that it doesn’t allow for rapid iterations on the frontend. With every change that is made to the UI, there is a high risk that now there is more (or less) data required than before. Consequently, the backend needs to be adjusted as well to account for the new data needs. 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 their exact data requirements, no backend engineer needs to make adjustments when the design and data needs on the frontend change.

Insightful Analytics on the Backend

GraphQL allows us to have fine-grained insights about the data that’s requested on the backend. As each client specifies exactly what information it’s interested in, it is possible to gain a deep understanding of how the available data is being used. This can for example help in evolving an API and deprecating specific fields that are not requested by any clients any more.

With GraphQL, we can also do low-level performance monitoring of the requests that are processed by our server. GraphQL uses the concept of resolver functions to collect the data that’s requested by a client. Instrumenting and measuring performance of these resolvers provides crucial insights about bottlenecks in our system.

Benefits of a Schema & Type System

GraphQL uses a strong type system to define the capabilities of an API. All the types that are exposed in an API 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 to define how a client can access the data.

Once the schema is defined, the teams working on frontend and backends can do their work without further communication since they both are aware of the definite structure of the data that's sent over the network.

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.

Challenges I faced

The challenge in building an API these days is the fundamental language constructs of GraphQL. This includes the first glimpse we take at the syntax for defining types as well as sending queries and mutations...it's totally unRESTful and very remiss of the days of running sql queries to fetch data.

So to help us get over the initial hump, here's how we break down core concepts of GraphQL where at the end we'll start a project.

The Schema Definition Language (SDL)

GraphQL has its own type system that’s used to define the schema of an API. The syntax for writing schemas is called Schema Definition Language (SDL).

Here is an example how we can use the SDL to define a simple type called Person:

type Person {
  name: String!
  age: Int!
}

This type has two fields, they’re called name and age and are respectively of type String and Int. The ! following the type means that this field is required.

It’s also possible to express relationships between types. In the example of a blogging application, a Person could be associated with a Post:

type Post {
  title: String!
  author: Person!
}

Conversely, the other end of the relationship needs to be placed on the Person type:

type Person {
  name: String!
  age: Int!
  posts: [Post!]!
}

Note that we just created a one-to-many-relationship between Person and Post since the posts field on Person is actually an array of posts.

Fetching Data with Queries

When working with REST APIs, data is loaded from specific endpoints. Each endpoint has a clearly defined structure of the information that it returns. This means that the data requirements of a client are effectively encoded in the URL that it connects to.

The approach that’s taken in GraphQL is radically different. Instead of having multiple endpoints that return fixed data structures, GraphQL APIs typically only expose a single endpoint. This works because the structure of the data that’s returned is not fixed. Instead, it’s completely flexible and lets the client decide what data is actually needed.

That means that the client needs to send more information to the server to express its data needs - this information is called a query.

Basic Queries

Let’s take a look at an example query that a client could send to a server:

{
  allPersons {
    name
  }
}

The allPersons 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 name.

This query would return a list of all persons currently stored in the database. Here’s an example response:

{
  "allPersons": [
 "Johnny" },
    { "name": "Sarah" },
    { "name": "Alice" }
  ]
}

Notice that each person only has the name in the response, but the age 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 needed the persons' age, all it has to do is slightly adjust the query and include the new field in the query’s payload:

{
  allPersons {
    name
    age
  }
}

One of the major advantages of GraphQL is that it allows for naturally querying nested information. For example, if we wanted to load all the posts that a Person has written, we could simply follow the structure of our types to request this information:

{
  allPersons {
    name
    age
    posts {
      title
    }
  }
}

Queries with Arguments

In GraphQL, each field can have zero or more arguments if that's specified in the schema. For example, the allPersons field could have a last parameter to only return up to a specific number of persons. Here's what a corresponding query would look like:

{
  allPersons(last: 2) {
    name
  }
}

Writing Data with Mutations

Next to requesting information from a server, the majority of applications also need some way of making changes to the data that’s currently stored in the backend. With GraphQL, these changes are made using so-called mutations. There generally are three kinds of mutations:

  • creating new data
  • updating existing data
  • deleting existing data

Mutations follow the same syntactical structure as queries, but they always need to start with the mutation keyword. Here’s an example for how we might create a new Person:

mutation {
  createPerson(name: "Bob", age: 36) {
    name
    age
  }
}

Notice that similar to the query we wrote before, the mutation also has a root field - in this case it's called createPerson. We also already learned about the concepts of arguments for fields. In this case, the createPerson field takes two arguments that specify the new person's name and age.

Like with a query, we're also able to specify a payload for a mutation in which we can ask for different properties of the new Person object. In our case, we’re asking for the name and the age - though admittedly that’s not super helpful in our example since we obviously already know them as we pass them into the mutation. However, being able to also query information when sending mutations can be a very powerful tool that allows us to retrieve new information from the server in a single roundtrip!

The server response for the above mutation would look as follows:

"createPerson": {
  "name": "Bob",
  "age": "36",
}

One pattern we'll often find is that GraphQL types have unique IDs that are generated by the server when new objects are created. Extending our Person type from before, we could add an id like this:

type Person {
  id: ID!
  name: String!
  age: Int!
}

Now, when a new Person is created, we could directly ask for the id in the payload of the mutation, since that is information that wasn’t available on the client beforehand:

mutation {
  createPerson(name: "Alice", age: 36) {
    id
  }
}

Realtime Updates with Subscriptions

Another important requirement for many applications today is to have a realtime connection to the server in order to get immediately informed about important events. For this use case, GraphQL offers the concept of subscriptions.

When a client subscribes to an event, it will initiate and hold a steady connection to the server. Whenever that particular event then actually happens, the server pushes the corresponding data to the client. Unlike queries and mutations that follow a typical “request-response-cycle”, 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 on events happening on the Person type:

subscription {
  newPerson {
    name
    age
  }
}

After a client sent this subscription to a server, a connection is opened between them. Then, whenever a new mutation is performed that creates a new Person, the server sends the information about this person over to the client:

{
  "newPerson": {
    "name": "Jane",
    "age": 23
  }
}

Key takeaways

Defining a Schema

Now that we have a basic understanding of what queries, mutations, and subscriptions look like, let’s put it all together and learn how we can write a schema that would allow us to execute the examples we’ve seen so far.

The schema is one of the most important concepts when working with a GraphQL API. It specifies the capabilities of the API and defines how clients can request the data. It is often seen as a contract between the server and client.

Generally, a schema is simply a collection of GraphQL types. However, when writing the schema for an API, there are some special root types:

type Query { ... }
type Mutation { ... }
type Subscription { ... }

The Query, Mutation, and Subscription types are the entry points for the requests sent by the client. To enable the allPersons-query that we saw before, the Query type would have to be written as follows:

type Query {
  allPersons: [Person!]!
}
```i
`allPersons` is called a *root field* of the API. Considering again the example where we added the `last` argument to the `allPersons` field, we'd have to write the `Query` as follows:

```graphql(nocopy)
type Query {
  allPersons(last: Int): [Person!]!
}

Similarly, for the createPerson-mutation, we’ll have to add a root field to the Mutation type:

type Mutation {
  createPerson(name: String!, age: Int!): Person!
}

Notice that this root field takes two arguments as well, the name and the age of the new Person.

Finally, for the subscriptions, we’d have to add the newPerson root field:

type Subscription {
  newPerson: Person!
}

Putting it all together, this is the full schema for all the queries and mutation that we have see so far:

type Query {
  allPersons(last: Int): [Person!]!
}

type Mutation {
  createPerson(name: String!, age: Int!): Person!
}

type Subscription {
  newPerson: Person!
}

type Person {
  name: String!
  age: Int!
  posts: [Post!]!
}

type Post {
  title: String!
  author: Person!
}

Tips and advice

As you can see, learning GraphQL is rather fun and easy if you've been developing on a range of technologies over the years, as you'll pick up the best of breed methods and implementations permeating throughout the GraphQL ecosystem.

If you're newer to building apps for production use, then you'll love the powerful and easy to use serverless toolchain that comes with building GraphQL powered applications.

Project time

Since it's always essential to practice, let's prepare a sandbox environment to experiment with what we've learned so far.

Final thoughts and next steps

React & Apollo Quickstart project

See the Relay Tutorial instead

For this quickstart, we have prepared a repository that contains the full React code for an Instagram clone. All you need to do is create a Graphcool service that will expose the GraphQL API and connect it with the React application. Let's get started!

Clone the example repository that contains the React application:

git clone https://github.com/graphcool-examples/react-graphql.git
cd react-graphql/quickstart-with-apollo

Feel free to get familiar with the code. The app contains the following React components:

  • Post: Renders a single post item
  • ListPage: Renders a list of post items
  • CreatePage: Allows to create a new post item
  • DetailPage: Renders the details of a post item and allows to update and delete it

Graphcool services are managed with the Graphcool CLI. So before moving on, you first need to install it.

Install the Graphcool CLI:

npm install -g graphcool

Now that the CLI is installed, you can use it to create the file structure for new service with the graphcool init command.

Create the local file structure for a new Graphcool service inside a directory called server:

# Create a local service definition in a new directory called `server`
graphcool init server

graphcool init creates the local service structure inside the specified server directory:

.
└── server
    ├── graphcool.yml
    ├── types.graphql
    └── src
        ├── hello.graphql
        └── hello.js

Each of the created files and directories have a dedicated purpose inside your Graphcool service:

  • graphcool.yml: Contains your service definition.
  • types.graphql: Contains the data model and any additional type definitions for your Graphcool service, written in the GraphQL Schema Definition Language (SDL).
  • src: Contains the source code (and if necessary GraphQL queries) for the functions you've configured for your service. Notice that a new service comes with a default "Hello World"-function (called hello in graphcool.yml) which you can delete if you don't want to use it.
  • package.json: Specifies the dependendies for your functions (if needed).

Next you need to configure the data model for your service.

Open ./server/types.graphql and add the following type definition to it (feel free to delete the existing User type):

type Post @model {
  id: ID! @isUnique    # read-only (managed by Graphcool)
  createdAt: DateTime! # read-only (managed by Graphcool)
  updatedAt: DateTime! # read-only (managed by Graphcool)

  description: String!
  imageUrl: String!
}

The changes you introduced by adding the Post type to the data model are purely local so far. So the next step is to actually deploy the service!

Navigate to the server directory and deploy your service:

cd server
graphcool deploy

When prompted which cluster you want to deploy to, choose any of the Shared Clusters options (shared-eu-west-1, shared-ap-northeast-1 or shared-us-west-2).

Note: If you haven't authenticated with the Graphcool CLI before, this command is going to open up a browser window and ask you to login. Your authentication token will be stored in the global ~/.graphcoolrc.

You service is now deployed and available via the HTTP endpoints that were printed in the output of the command! The Post type is added to your data model and the corresponding CRUD operations are generated and exposed by the GraphQL API.

Notice that this command also created the local .graphcoolrc inside the current directory. It's used to manage your deployment targets.

Save the HTTP endpoint for the Simple API from the output of the graphcool deploy command, you'll need it later!

Note: If you ever lose the endpoint for your GraphQL API, you can simply get access to it again by using the graphcool info command. When using Apollo, you need to use the endpoint for the Simple API.

You can test the API inside a GraphQL Playground which you can open with the graphcool playground command. Feel free to try out the following query and mutation.

Fetching all posts:

query {
  allPosts {
    id
    description
    imageUrl
  }
}

Creating a new post:

mutation {
  createPost(
    description: "A rare look into the Graphcool office"
    imageUrl: "https://media2.giphy.com/media/xGWD6oKGmkp6E/200_s.gif"
  ) {
    id
  }
}

The next step is to connect the React application with the GraphQL API from your Graphcool service.

Paste the HTTP endpoint for the Simple API that you saved after running graphcool deploy into ./src/index.js as the uri argument in the HttpLink constructor call:

// replace `__SIMPLE_API_ENDPOINT__` with the endpoint from the previous step
const httpLink = new HttpLink({ uri: '__SIMPLE_API_ENDPOINT__' })

That's it. The last thing to do is actually launching the application 🚀

Install dependencies and run the app:

yarn install
yarn start # open http://localhost:3000 in your browser

Congrats! You did it!!! 🚀

In the next post, we'll explore more of the big picture with GraphQL architecture with clients, server(less), tooling, and security.


Apollo Tutorial provided by Graph.cool & examples by How To Graphql

Discover and read more posts from Joel Serino
get started
post commentsBe the first to share your opinion
Show more replies