GraphQL vs REST: putting REST to rest

GraphQL vs REST: putting REST to rest

When you need to build an API, your mind will likely jump to REST, the de facto standard for API creation. However, this is about to change with GraphQL, as its popularity quickly rises.

When you need to build an API, your mind will likely jump to REST, the de facto standard for API creation. However, this is about to change with GraphQL, as its popularity quickly rises.

Not everyone fully understands yet what GraphQL is all about, or why it's being declared as the successor of REST, and that's exactly what I'll clear up in this article. Here I'll show off GraphQL's main features and the advantages that it has over REST, highlighting a few points in which both differ.

The goal is to provide a brief explanation to anyone who still hasn't got to know GraphQL, and clarify exactly what it does better than REST, for those who are still skeptic about this technology.

Let's start with the very basics.

What is GraphQL?

GraphQL is a query language for APIs that enables declarative data fetching in order to give the client the power to specify exactly the data that is needed from the API.

A question that I see asked a lot is:

Why was GraphQL created when we already have REST?
There are two main reasons why companies such as Facebook, Netflix and Coursera started developing alternatives to REST:

1. In the early 2010s there was a boom in mobile usage, which led to some issues with low-powered devices and sloppy networks. REST isn't optimal to deal with those problems;

2. As mobile usage increased, so did the number of different front-end frameworks and platforms that run client applications. Given REST's inflexibility, it was harder to develop a single API that could fit the requirements of every client.

If we go even further, we realize that the main reason why an alternative solution was identified was because most of the data used in modern web and mobile applications has a graph shape. For instance, newspieces have comments, and those comments may have features such as likes or spam flags, which are created or reported by users. This example describes how a graph looks like.

Consequently, Facebook started developing GraphQL. At the same time, Netflix and Coursera were also working on alternatives themselves. After Facebook open-sourced GraphQL, Coursera dropped their efforts and adopted the new tech. Netflix, however, continued developing their own REST alternative and later open sourced Falcor.

What GraphQL isn't

Now that we know what GraphQL is, I want to clarify what it is not, as I feel that there's still some confusion about it.

Firstly, it doesn't have anything to do with databases. It isn't an alternative to SQL or a brand new ORM.

Secondly, it isn't a REST replacement, but an alternative. You don't have to pick between one and the other, they can happily co-exist in the same project.

Last but not least, GraphQL isn't complicated or scary. It's quite easy to understand its declarative nature and exactly how it's possible to take the best from it.

GraphQL in context

Before moving on to the comparison with REST, I'll go through a simple GraphQL query where we can fetch a user as well as his or her name and age:

query {
  user {
    name
    age
  }
}

And the JSON response we'll get from it:

{
  "user": {
    "name": "Johnathan Joestar",
    "age": 27
   }
}

As I stated previously, GraphQL's declarative nature makes it incredibly easy to understand what's going on at all times, as we are basically writing JSON objects without the values.

Now that we have context, let's dive deep into GraphQL's features and the advantages that it has over REST.

GraphQL vs REST

In this section I'll go point by point through a practical example, comparing REST to GraphQL in order to demonstrate the flexibility of Facebook's query language.

Imagine that you have a blog, and you want the front page to show all the latest posts. In order to achieve this, you need to fetch the posts, so you will probably do something like this:

GET /api/posts

[
  {
    "title": "Cooler post",
    "subtitle": "...",
    "date": "07/05/2019"
  },
  {
    "title": "Cool post",
    "subtitle": "...",
    "date": "06/05/2019"
  }
]

But what if you want to see the author as well? You have three options to achieve this:

  • Fetch the authors from another resource:
GET /api/post/:id

{
  "post": {
    ...,
    "author": {
      "name": "Dio Brando"
    }
  }
}

  • Modify the resource to also return the author:
GET /api/posts

[
  {
    ...,
    "author": {
      "name": "Dio Brando"
    }
  },
  {
    ...,
    "author": {
      "name": "Johnathan Joestar"
    }
  }
]

  • Create a new resource that returns the posts with the author:
GET /api/postsWithAuthor

[
  {
    ...,
    "author": {
      "name": "Dio Brando"
    }
  },
  {
    ...,
    "author": {
      "name": "Johnathan Joestar"
    }
  }
]

Each of these approaches will create a problem of its own, so let's have a look at them one by one.

Under-fetching

With the first approach – fetching the authors from another resource – you'll end up with two server requests instead of one, and as you continue to scale, you may have even more requests to different endpoints in order to fetch all the needed data.

With GraphQL, this wouldn't happen. You would only have one request, and you wouldn't have to make multiple round trips to the server, as seen below:

query {
  posts {
    title
    subtitle
    date
    author {
      name
    }
  }
}

Over-fetching

Looking at the second approach – modifying the resource to also return the author – you can see that it solved the problem pretty nicely. However, changing a resource may have a secondary effect elsewhere on your application. More precisely, over-fetching.

Let's go back to your blog, but this time you also have a sidebar showing off the top monthly posts with their titles, subtitles and date, that is using the resource /api/posts. Since you modified the resource, now it also shows the author with it. However, we don't need it for the sidebar.

While this may not look like a problem, for users on limited data plans, having a website fetch useless data isn't ideal. Since GraphQL allows the client to only fetch the needed data, this problem wouldn't exist:

query {
  posts {
    title
    subtitle
    date
  }
}

Slow front-end development

Lastly, let's have a look at the last approach – creating a new resource that returns the posts with the author – since it's a common pattern to structure the endpoints according to the views in your project.

While this may solve problems such as the one described above, it also slows down the front-end development, since each specific view needs its specific endpoint. If at any point a view needs new data, the development has to slow down until the endpoint is updated.

Again, since GraphQL gives power to the client to fetch the needed data only, nothing slows down, as it's very simple to just add a new field to a query.

You would get from this:

query {
  posts {
    title
    subtitle
    date
  }
}

To this:

query {
  posts {
    title
    subtitle
    date
    author {
      name
    }
  }
}

REST vs GraphQL comparison recap

Let's just do a quick recap regarding the differences between REST and GraphQL:

  • GraphQL solves both over-fetching and under-fetching issues by allowing the client to request only the needed data;
  • Since the client now has more freedom in the fetched data, development is much faster with GraphQL than what it would be with REST.

Now we'll move on to a more in-depth overview of GraphQL's unique features.

GraphQL's features overview

Now that we know how it stacks up against REST, let's talk about some of the features that are unique to GraphQL.

Schema and Type System

GraphQL uses its own type system to define the schema of an API, with its syntax called Schema Definition Language (SDL). The schema serves as a contract between the server and the client to define how a client can access the data.

Once the schema is defined, the front-end and back-end teams can work independently, as the front-end can be easily tested with mock data. The front-end can also get useful information from the schema, such as its types, queries and mutations using GraphiQL or introspection. The schema also provides type safety, which is a plus for the front-end and back-end development, as it catches type errors early.

A schema example:

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

type Post {
  title: String!
  subtitle: String!
  body: String!
  date: String!
  author: User!
}

type Query {
  users: [User!]!
  user(name: String!): User!
  posts: [Post!]!
  post(title: String!): Post!
}

type Mutation {
  createUser(name: String!, age: Int): User!
  createPost(title: String!, subtitle: String!, body: String!): Post!
}

GraphQL IDE

This is one of the most useful features of GraphQL development. A GraphQL IDE takes advantage of its self-documenting nature to make development a breeze.

Using GraphiQL or GraphQL Playground, you can just inspect your schema and even run queries and mutations to test out your API.

GraphQL Playground

Wrap up

GraphQL provides a smooth and fast development environment with its declarative and flexible nature, offering many improvements over REST. Despite being relatively new, it has already been adopted by companies such as Facebook, GitHub and many more .

It already has a large community and a vibrant ecosystem, and was already implemented in several popular languages, such as JavaScript, Go and Java.

While this post only dipped the toes into the ocean that is GraphQL, its website has a plethora of information and is an amazing place to learn and start using GraphQL.

With all this being said, it's not a perfect technology, and it still has a couple of drawbacks when compared with REST. But considering how young it is, the future looks incredibly bright for GraphQL.

From REST To GraphQL

From REST To GraphQL

From REST to GraphQL: A different way to create an API (with Apollo & Node.js). Ready to make the jump to a GraphQL API? In this tutorial, we will cover how to create models based on your database, create a NodeJS GraphQL API that reads the data from the database, and learn how to make relations in your GraphQL API between different tables.

From REST to GraphQL: A different way to create an API (with Apollo & Node.js)

Ready to make the jump to a GraphQL API? If you already have a MySQL database you have an excellent starting point for creating a scalable API. In this tutorial, we will cover how to create models based on your database, create a NodeJS GraphQL API that reads the data from the database, and learn how to make relations in your GraphQL API between different tables.

In this tutorial, we will build a small GraphQL endpoint for a ticketing system. We want to create an endpoint where we can read tickets and get their associated data such as user, status, and priority.

The building blocks we will be using are:

  • (An existing) MySQL database
  • NodeJS
  • Express (web framework for Node.js)
  • Apollo (tools to create GraphQL endpoints)
  • Sequelize (Object-Relational Mapping package)
  • Webpack (to package the application)
  • Docker (to spin up a local MySQL database, it’s optional as long as you have a MySQL instance)

Don’t worry if you don’t know every piece I just noted, I will describe every step along the way. If you want to code along, you can check out this repository and clone the start of the tutorial release with this command:

git clone <https://github.com/DirkWolthuis/graphql-express-migrating-mysql> --branch start
Step 1: database layer

First, we’ll assume that we’re working with an existing database. I’ve created an SQL file that you can import into MySQL database. I like running my MySQL database inside a Docker container, you can use the docker-compose.yaml file (inside the repository) to start a MySQL container.

The database has four tables: tickets, priorities, status, and users. The tables have the following structure:

Tickets

| Field               | Type             | Null | Key | Default           | Extra          |
+---------------------+------------------+------+-----+-------------------+----------------+
| id                  | int(11) unsigned | NO   | PRI | NULL              | auto_increment |
| subject             | varchar(256)     | NO   |     | NULL              |                |
| priority_id         | int(11)          | NO   |     | NULL              |                |
| status_id           | tinyint(4)       | NO   |     | NULL              |                |
| user_id             | int(11)          | NO   |     | NULL              |                |
| assigned_to_user_id | int(11)          | YES  |     | NULL              |                |
+---------------------+------------------+------+-----+-------------------+----------------+

Users

| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(256)     | NO   |     | NULL    |                |
| email | varchar(256)     | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

Priorities

| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| slug  | varchar(64)      | NO   |     | NULL    |                |
| name  | varchar(256)     | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

Status

| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| slug  | varchar(64)      | NO   |     | NULL    |                |
| name  | varchar(256)     | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

Create your own database with the schematics above or import the SQL file into your MySQL database and we are ready to start coding. You can find the SQL file inside the repository in the directory tutorial_assets.

Step 2: bootstrapping the application

In the repository for this tutorial, I have set up Webpack to compile the app.js file inside the dist directory. It serves a basic Express Hello World app. After cloning the project you need to run npm install to install the dependencies.

Finished installing? You can run npm run start to start the app. It will serve an endpoint on http://localhost:5000.

Let’s start building our GraphQL API!

Step 3: creating the database models

Virtually every framework uses models to interact with a database. To interact with our MySQL database we’re using Sequelize as ORM (Object-Relational Mapping) package. Let’s start by adding the packages (the mysql2 package is necessary to connect to the MySQL database).

npm install sequelize mysql2

Now we can do one of two things, we can either create the database models by hand or auto-generate with an extra package. For this tutorial creating the models by hand would not be a problem, we have just four small tables in our database. But when you are migrating a bigger database you might want something more automated. Luckily, there is a package to generate Sequelize database files based on an existing database. The package is named Sequelize-Auto and it can be installed globally with NPM.

npm install -g sequelize-auto mysql

In order to migrate the database in a more automated way, we can use the sequelize-auto command. We need to insert our MySQL database credentials in the command to generate the models. If you are using the provided MySQL dump from step 1, I’ve created a config JSON file that you need to use.

The sequelize-auto-settings.json is located in the tutorial_assets directory. If you’re using your own database for this tutorial, check out this settings page on Sequelize API documentation to find out what settings you need.

sequelize-auto -h <host> -d <database> -u <user> -x [password] -p [port]  --dialect [dialect] -c [/path/to/config] -o [/path/to/models]

So in my case:

sequelize-auto -h localhost -d graphql-mysql-tutorial -u graphql -x 123456 -p 8006  --dialect mysql -c /Users/wolthuis/Documents/websites/tutorials/graphql-migrating-mysql/tutorial_assets/sequelize-auto-settings.json -o /Users/wolthuis/Documents/websites/tutorials/graphql-migrating-mysql/app/models

And there we go! Four files appeared in app/models directory. In our file let’s start with importing Sequelize and setting up some variables.

Step 4: implementing the database models

We now need to implement the database models. In the app, directory create a database.js file. In this file, we import the database models and export them so we can use them anywhere in our app.

const Sequelize = require('sequelize')

var db = {}

const sequelize = new Sequelize(
    'DATABASE_NAME',
    'DATABASE_USER',
    'DATABASE_PASSWORD',
    {
        host: 'DATABASE_HOST',
        port: 'DATABASE_PORT',
        dialect: 'mysql',
        define: {
            freezeTableName: true,
        },
        pool: {
            max: 5,
            min: 0,
            acquire: 30000,
            idle: 10000,
        },
        // <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
        operatorsAliases: false,
    },
)

let models = []

// Initialize models
models.forEach(model => {
    const seqModel = model(sequelize, Sequelize)
    db[seqModel.name] = seqModel
})

// Apply associations
Object.keys(db).forEach(key => {
    if ('associate' in db[key]) {
        db[key].associate(db)
    }
})

db.sequelize = sequelize
db.Sequelize = Sequelize

module.exports = db

Okay so we need to do two things, fill in our MySQL database credentials and import the freshly created models. Normally you would use environment variables to safely pass around sensitive data, but for tutorial purposes, I’m just going to hard code some values inside the database.js file.

So the database.js file with credentials in imports looks something like this:

const Sequelize = require('sequelize')

var db = {}

const sequelize = new Sequelize('graphql-mysql-tutorial', 'graphql', '123456', {
    host: 'localhost',
    port: '8006',
    dialect: 'mysql',
    define: {
        freezeTableName: true,
    },
    pool: {
        max: 5,
        min: 0,
        acquire: 30000,
        idle: 10000,
    },
    // <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
    operatorsAliases: false,
})

let models = [
    require('./models/priorities.js'),
    require('./models/status.js'),
    require('./models/tickets.js'),
    require('./models/users.js'),
]

// Initialize models
models.forEach(model => {
    const seqModel = model(sequelize, Sequelize)
    db[seqModel.name] = seqModel
})

// Apply associations
Object.keys(db).forEach(key => {
    if ('associate' in db[key]) {
        db[key].associate(db)
    }
})

db.sequelize = sequelize
db.Sequelize = Sequelize

module.exports = db

Great, we can now import the db variable anywhere in our app and access all of our models. In the next steps, we are surely going to use that variable to access our data.

Step 5: setting up an Apollo server

Apollo is a layer built on top of the GraphQL specification and they provide excellent developer tools. They also provide a package to integrate Apollo server into an (existing) Express application. We are going to use this package, in my experience, the best way to create a GraphQL API is to sometimes fall back on a normal rest API. For example, when creating an authentication endpoint I prefer to keep GraphQL and the authentication routes completely separated.

To start, we first need to add two packages:

npm install apollo-server-express graphql

After installing we need to do some setup inside app.js to couple Apollo and Express. We start by importing ApolloServer:

const { ApolloServer } = require('apollo-server-express')

Then we create a new instance of the Apollo server:

const server = new ApolloServer({
        modules: []
})

And the last step we apply the Apollo server as middleware on the existing Express app:

server.applyMiddleware({ app })

We can’t yet start our app, without any modules Apollo server will throw an error. So in the next step, we are going to implement our database entities into GraphQL endpoint so we can reach them with a GraphQL query.

Step 6: creating our GraphQL types and resolvers

In GraphQL, you need types and resolvers. Types describe the data you can either fetch or write via a GraphQL endpoint. Resolvers are the logic to resolve a request from a user.

Inside of the GraphQL directory, we create a new file with the name tickets.js. Inside this file we will include a variable from the apollo-server-express package that we’ll use to create GraphQL type definitions, include our db variable and two empty objects for our type GraphQL definitions and GraphQL resolvers.

import { gql } from 'apollo-server-express'
import * as db from '../database'

export const typeDefs = gql`
   
`
export const resolvers = {
}
Creating the GraphQL types

So first we’re filling the typeDefs variable. You can see that we are using the gql variable from the apollo-server-express package. The gql variable lets us write type definitions that are readable for the package.

In the typeDefs variable we need to do two things, extend the Query type and create a new type called Ticket. The reason that we need to extend the Query type is because GraphQL always works with a top-level type called Query. Inside that type are other types nested and that’s how GraphQL knows with types are available in your GraphQL API.

Okay so let’s extend the Query type:

export const typeDefs = gql`
    extend type Query {
        tickets: [Ticket]
        ticket(id: ID!): Ticket
    }
    type Ticket {
       
    }
`

So in the code above we did a couple of things. We let GraphQL know we want to extend the Query with two new entities: ticket and tickets.

Tickets returns an array of tickets:

tickets: [Ticket]

Ticket returns a single type of Ticket. The ticket type will receive an argument called id, of type ID and can’t be null (so in other words, the argument is required). The exclamation mark in a GraphQL type symbolizes that a value can’t be null:

ticket(id: ID!): Ticket

For now our Ticket type is empty, so let’s fill in this type:

export const typeDefs = gql`
    extend type Query {
        tickets: [Ticket]
        ticket(id: ID!): Ticket
    }
    type Ticket {
        id: ID!
        subject: String
        priority_id: Int
        status_id: Int
        user_id: Int
        assigned_to_user_id: Int
    }
`

So in the above code, we described which types the ticket type is composed of. It is a 100% match with our database model. This is true for now but will change in the future when we are going to add relations between our types/models.

Creating the GraphQL resolvers

So we created our types for the ticket entity. Now let’s create the resolver. The resolver needs to more or less reflect our types. Inside the resolver object, we also start with a top-level Query object.

export const resolvers = {
    Query: {},
}

Inside the query, we reflect our query type so we add two keys: ticket and tickets. We use our db (database) variable to resolve the data from the database.

export const resolvers = {
    Query: {
        tickets: async () => db.tickets.findAll(),
        ticket: async (obj, args, context, info) =>
            db.tickets.findByPk(args.id),
    },
}

A resolver receives a couple of arguments we can use to resolve the delete request. The obj is the root object, we will use this root object to make relations. The args are the function arguments we defined in the types. So in case of our tickets it’s an ID of the ticket we need to get. If you want to read more about obj, args, context, info check out the Apollo Docs.

Adding the ticket module to our Apollo server

So we’ve created a module, we just need to import it into our application inside the app.js. To do so, add the module:

const server = new ApolloServer({
    modules: [require('./GraphQL/tickets')],
})

Now do the same for priorities, users, and status and also import those modules:

const server = new ApolloServer({
    modules: [
        require('./GraphQL/tickets'),
        require('./GraphQL/status'),
        require('./GraphQL/users'),
        require('./GraphQL/priorities'),
    ],
})

After starting the app again, go to localhost:5000/graphql and you will come into the Apollo GraphQL query builder environment. In this environment, you can test your API and create queries that you will use later in other applications. Also, you can explore your API with the docs button on the right side. Because GraphQL is typed, you automatically have API documentation. Pretty cool!

Step 7: creating relations between data

So this is pretty cool, but it would be nice to automatically get the users name when getting a ticket. In the current state of our application, we can only get the user id associated with the ticket. In this step, we will create a relation between the ticket and the users.

Adding the user type on the ticket type

So first let’s edit the Ticket type. We need to let GraphQL know that we want to request a user of the type user:

export const typeDefs = gql`
    extend type Query {
        tickets: [Ticket]
        ticket(id: ID!): Ticket
    }
    type Ticket {
        id: ID!
        subject: String
        priority_id: Int
        status_id: Int
        user_id: Int
        user: User
        assigned_to_user_id: Int
    }
`
Adding an extra resolver for the user

Next, we need to add a nested resolver that will resolve the user inside the ticket. In the resolver object, we are going to add the key Ticket.That’s how GraphQL knows to resolve nested queries when we request a type inside an other type. In this case resolver, the User type, inside the Ticket type:

export const resolvers = {
    Query: {
        tickets: async () => db.tickets.findAll(),
        ticket: async (obj, args, context, info) =>
            db.tickets.findByPk(args.id),
    },
    Ticket: {
        user: async (obj, args, context, info) => db.users.findByPk(obj.user_id),
    },
}

You see we are using the obj to access the ticket data. In the ticket data the user_id is set, so we can get the right user from the database.

So let’s see if our code works. I’ve created this query to see if I can get the nested user data. Take note that you also need to specify which fields you want from the user type, in my case the id, name and email field.

{
  ticket(id: 3){
    id
    subject
    user{
      id
      name
      email
    }
  }
}

Great, it works! This is what Apollo returns:

Now add the other relationships the same way: priority, status and assigned_to_user. After finishing adding the other nested resolver your tickets.js file will look something like this:

import { gql } from 'apollo-server-express'
import * as db from '../database'
export const typeDefs = gql`
    extend type Query {
        tickets: [Ticket]
        ticket(id: ID!): Ticket
    }
    type Ticket {
        id: ID!
        subject: String
        priority_id: Int
        priority: Priority
        status_id: Int
        status: Status
        user_id: Int
        user: User
        assigned_to_user_id: Int
        assigned_to_user: User
    }
`
export const resolvers = {
    Query: {
        tickets: async () => db.tickets.findAll(),
        ticket: async (obj, args, context, info) =>
            db.tickets.findByPk(args.id),
    },
    Ticket: {
        user: async (obj, args, context, info) =>
            db.users.findByPk(obj.user_id),
        priority: async (obj, args, context, info) =>
            db.priorities.findByPk(obj.priority_id),
        status: async (obj, args, context, info) =>
            db.status.findByPk(obj.status_id),
        assigned_to_user: async (obj, args, context, info) =>
            db.users.findByPk(obj.assigned_to_user_id),
    },
}

Go to localhost:5000/graphql and construct a query that gets all the tickets with their status, priorities and users. With this query:

{
  tickets{
    subject
    status{
      slug
    }
    priority{
      slug
    }
    user{
      name
    }
    assigned_to_user{
      name
    }
  }
}

I get the following tickets and their attributes:

{
  "data": {
    "tickets": [
      {
        "subject": "My computer is on fire🔥🔥",
        "status": {
          "slug": "open"
        },
        "priority": {
          "slug": "high"
        },
        "user": {
          "name": "Dirk Wolthuis"
        },
        "assigned_to_user": null
      },
      {
        "subject": "MS Word is not starting, can someone help?",
        "status": {
          "slug": "doing"
        },
        "priority": {
          "slug": "low"
        },
        "user": {
          "name": "Chris Vogt"
        },
        "assigned_to_user": {
          "name": "Dirk Wolthuis"
        }
      },
      {
        "subject": "There is a bug in the 🛒 of the webshop, steps to reproduce are included",
        "status": {
          "slug": "doing"
        },
        "priority": {
          "slug": "high"
        },
        "user": {
          "name": "Andrew Clark"
        },
        "assigned_to_user": {
          "name": "Dirk Wolthuis"
        }
      },
      {
        "subject": "404 error: website not found - website down?💀",
        "status": {
          "slug": "closed"
        },
        "priority": {
          "slug": "high"
        },
        "user": {
          "name": "Andrew Clark"
        },
        "assigned_to_user": {
          "name": "Dirk Wolthuis"
        }
      }
    ]
  }
}
Conclusion

We’ve created a usable GraphQL API that you can customize any way you want. You can add multiple layers of relationships between entities. And after creating a new database table you can easily create the required Sequelize models for your application. For the sake of this tutorial, we’ve created a read-only database. Just want to check out the code? You can find it in this repository. If you want to learn more about how to manipulate data in the database, you can check out Designing Mutations or read this post about Mutations. The setup of the server is a little bit different, but the logic is the same.

GraphQL vs REST

GraphQL vs REST

In this article, we’ll take a look at both REST and GraphQL. We’ll briefly explain how each works and compare the pros and cons to using REST vs GraphQL in developing your web service.

REST is an architectural approach to creating web services. GraphQL is a query language for designing APIs. Both are used to create web services allowing clients to communicate with remote servers over HTTP.

While REST has been widely accepted as the “de facto” for developing stateless independent microservices, GraphQL is the new kid on the block for rapid API development.



What is REST?

REST stands for Representational State Transfer. REST isn’t a library but rather an architectural “way of doing things”. Web services are considered RESTful when their implementation adheres to REST principles.

A core concept behind REST is the idea of resources. A resource represents a piece of data you want to retrieve from the server. If your web app is a blog then resources may include posts, comments, users, etc.

Each resource is identified by a URL. You fetch a given resource by sending a HTTP request that may look something like this:

/users/<id>/posts

The server processes your request and returns something like this:

{
  "posts": [
    {
      "title":"My latest post",
      "author":"Sam",
      "views":33
    },
    {
      "title":"My other post",
      "author":"Sam",
      "views":14
    },
    {
      "title":"My first post",
      "author":"Sam",
      "views":53
    }
  ]
}

For a user with a given , the service returns a JSON object with an array of post objects.


What is GraphQL?

Unlike REST, GraphQL is an actual application query language for making HTTP requests that return specified resources. While GraphQL ultimately uses the same HTTP protocol to retrieve information from the server, it leverages a type system defined in a schema. This schema dictates the types of queries that can be run and the data they return.

Unlike REST, GraphQL produces a single API endpoint for communicating with the server.

Let’s see how GraphQL would implement the same REST call from the previous example:

query {
  User(id: <id>) {
    posts {
      title,
      author,
      views
    }
  }
}

The server processes the request and returns:

{
  "posts": [
    {
      "title":"My latest post",
      "author":"Sam",
      "views":33
    },
    {
      "title":"My other post",
      "author":"Sam",
      "views":14
    },
    {
      "title":"My first post",
      "author":"Sam",
      "views":53
    }
  ]
}

Notice how the exact same JSON response is returned using GraphQL…


So whats the point?

From the examples, it looks like both GraphQL and REST produce the same result. The GraphQL query seems a bit more verbose than a simple GET request, but both ultimately use the same protocol to return the same thing. So what’s the big deal?


Overfetching and underfetching data

One of the main reasons why GraphQL is preferred to REST is the precision with which data is retrieved from the server. While our basic /users//posts endpoint gave us the data we needed, it may have given us more than we asked for. For example, what if we only wanted the title returned for each post?

This is known as “overfetching” since we got back more than we asked for. Specifically, we got back the author and views along with the title.

Another scenario could be that you need more information about each post. In addition to views, authors, and titles you may also want the number of likes for a given post, etc. This is considered “underfetching” and results in additional requests needed for each post object being returned.

You may be thinking…so what? After all, you could modify the REST endpoint to accept parameters for each field you want returned. You could even filter at the database level or create a new endpoint all together.

And you aren’t wrong. But this would require more development work and more coordination across different teams.

Alternatively, with GraphQL we could simply modify our original query to address the “overfetching” problem:

query {
  User(id: <id>) {
    posts {
      title
    }
  }
}

or the “underfetching” problem:

query {
  User(id: <id>) {
    posts {
      title,
      author,
      views,
      followers
    }
  }
}

Notice how in both cases we simply add or subtract fields that we want returned. Remember GraphQL uses the same API endpoint for every query…so no need to bug the API team.


One request to rule them all…

This example clearly illustrates the benefits of using GraphQL over REST. By specifying a clearly designed schema with the data types and queries available, GraphQL implements a more contract-driven approach to communicating with the server.

This better isolates the front end from the back end and allows for more rapid API development as quickly evolving UIs can retrieve the exact information they need.


GraphQL vs REST: Pros and Cons

So should you forget about REST completely? Not at all. It’s important to remember that REST remains one of the most popular approaches to microservice architecture. Deciding between GraphQL vs REST depends on how you emphasize the pros and cons of each.


REST pros:

  • widely accepted- REST has been around since 2000 and remains one of the most popular approaches to implementing web services today.
  • reusable - using REST, you can more easily develop independent microservices that work independently of one another. Microservices are (ideally) fully decoupled from clients allowing for them to be accessed by multiple applications.
  • caching - REST inherently supports caching much better than GraphQL. This makes for better performance out of the box.

REST cons

  • excessive round trips - more endpoints requires more requests. We saw how the problem of underfetching can lead to excessive requests over the network.
  • versioning - to avoid breaking changes, REST APIs must implement versioning to ensure production services continue working even when updates are made. This can get messy as more and more versions of your API are released.
  • overfetching - downloading unnecessary data
  • underfetching - not retrieving enough data, resulting in additional requests
  • coordination efforts - it’s more difficult to develop front ends independently of back ends since new requirements require new endpoints (or modification of existing endpoints).

GraphQL pros

  • schema - by defining a schema with types of data and queries, GraphQL creates a contract between the client and the server making the data available to the client more obvious. Front end developers don’t need to concern themselves with back end.
  • easy to get started - you don’t have to be an expert with web service architecture to start producing / consuming GraphQL.
  • precision - you can retrieve exactly the data you’re looking for without additional endpoints or modification of those endpoints. GraphQL more efficiently addresses the overfetching/underfetching problem.

GraphQL cons

  • scalability issues - GraphQL is easy to get started with, but can become more of a performance issue as complex queries surface and grow.
  • schema limitations - With GraphQL, you’re stuck with the schema that’s defined. This can cause headaches when you want more in-depth responses than provided.
  • still fairly new - GraphQL is still considered the new kid on the block. There are only a few select clients that implement it well (Apollo, Relay, and Lokka among the most popular GraphQL clients).
Conclusion

While arguing the pros and cons of GraphQL vs REST can be a never ending conversation, it’s important to remember that both achieve the same end result. Both invovle sending HTTP requests and receiving data from a server. Both have the idea of resources and can specify IDs for those resources. Both can return JSON responses.

Answering the question as to which is better for your web service really depends on the dynamic between different dev teams in your organization. If you already follow a microservice architecture, then dropping REST to play with GraphQL may not be the best idea. However if your team emphasizes rapid API development driven by the front end, then GraphQL may be the best fit for you.


Originally published at https://www.stackchief.com

The fundamental differences between GraphQL and REST

The fundamental differences between GraphQL and REST

Have you heard of GraphQL and not entirely sure how it is different from REST? In this post, we are going to address the fundamental differences between GraphQL and REST.

A quick introduction to GraphQL

In this post, I am not going to focus on explaining what GraphQL is, instead we are going to compare how it is different from REST. But if you are new to GraphQL, here is the long story short. GraphQL is the new kid in the block and is an alternative to writing APIs using REST.

It was developed by Facebook as an internal solution for their mobile apps, and was later open sourced to the community. Ever since then, it has been widely popular among developers and has become a favorite solution for building services.

GraphQL is a query language and is agnostic of the language you use. It is just a specification. The client can query for the data they need from the server. And the server responds back with a JSON response to the query. The interesting thing to note here is that, the client can ask for exactly what they need, and they receive only that. Yes!

Isn’t that interestingly different from the REST approach? Let’s dive in and learn their differences.

1. Data Fetching

Let’s assume that we want to access the data in the programmingwithmosh.com blog. I want to build an app, that displays the blog author information. I want it to display the name of the author, the blog posts written by the author and the three most recent blog topics written by the author.

REST

In Representation State Transfer (REST), we call an endpoint, to request the data that we need. The server then responds back with the response. If we were to use REST APIs, then I would first have an endpoint that could be:

/blog/author/<id>

This endpoint would fetch the author’s information. I would then need another endpoint to access the blog posts.

/blog/author/<id>/posts

And finally I would need another endpoint to get the blog topics.

/blog/author/<id>/topics

Multiple round-trips with REST

You get the idea, this is the typical number of roundtrips that you will have to make while using REST to get the data that you need. REST endpoints get out of control, as our data needs expand. This leads to multiple round-trips, and causes a slowness in response time.

Over-fetching and Under-fetching Problems with REST

Often with REST, you will end up with data that you don’t need. For example, when calling the blog/author/<id> endpoint, you will get all the data pertaining to the author. You could get back data like, date_created, date_updated, age, gender and so on. But all we needed was the author’s name. This is a classic example of over-fetching in REST.

In the case of under-fetching, you can notice here that just the call to blog/author/<id> was not sufficient to retrieve what we are looking for. To get the last three posts written by the author, we had to make a call to another endpoint blog/author/<id>/posts. This situation is called under-fetching.

GraphQL

Guess what happens in the GraphQL world? You write one query to ask for what you want, and you get back exactly what you asked for.

There are no multiple round-trips to fetch data in GraphQL

This will make more sense if you see the actual query and the response received.

GraphQL Query Request

This is how our query will look like. We pass in the fields that we need response for. We are looking for the author’s name, last three blog posts written, and the last three topics they wrote. The query is structured to ask exactly what we need.

 {
 author (id: 6) {
   name 
   posts (last: 3) {
     title
   }
   topics (last : 3) {
    name
   }
 }
}

GraphQL Query Response

Here is what we get back from the server.

{
 "data" : {
   "author" : {
     "name" : "Adhithi Ravichandran",
     "posts" : [
       { title: "React vs. Vue : A Wholesome Comparison"},
       { title: "React Lifecycle Methods: A Deep Dive"},
       { title: "5 Essential Skills A Frontend Developer Should Possess"}
     ],
     "topics" : [
       { name: "React and Vue"},
       { name: "React"},
       { name: "General"}
     ]
   }
 }
}

We got a JSON response back from the server that has exactly what we asked for. It has returned the author name, the last three posts written by the author and the last three topics authored by author. Nothing more, nothing less and everything in a single trip to the server. Isn’t this amazing?!

GraphQL: No multiple rounds trips to server, no over-fetching and no under-fetching of data

The differences in data fetching are the biggest differences between REST and GraphQL.

2. Rapid Product Development on Frontend

While using REST APIs, client teams that are using the APIs have to wait for the backend team to complete their development of APIs, to start using them. Often, the frontend team sees slowness in development because of this prolonged waiting for APIs from the backend team. I have been a part of this situation several times, where the frontend developer’s hands are tied until the backend hands over a working version of their API.

This leads to slowness in development, and a huge reliance on the backend team to deliver faster so that the client team can start their work to consume the API.

In the GraphQL world, there is a different approach. The frontend and backend teams can develop in parallel, without stalling the development.

GraphQL: Teams work in parallel, leading to rapid product development

The frontend teams can work with mock versions of the API, and also use libraries like GraphQL Faker to create fake data. Coding can be completely done with mock data and tests can be written too. When the backend team is ready with the APIs, the mock API can be switched with the real API.

No Versioning of API in GraphQL – Non-breaking changes

With the idea that you ask for only what you need, GraphQL APIs do not need versioning. This means the changes made to the API are not breaking changes. Updates can be added to API, without affecting the client. Overall, GraphQL provides a much more pleasant experience to the developers and enables teams to work independently.

3. Community and Ecosystem

The GraphQL community has grown a lot in the last few years. The growing community interest in GraphQL has resulted in an all encompassing ecosystem with developer friendly tools. There are plenty of client and server libraries for GraphQL, making development much easier.

REST is a traditional approach, and has an established ecosystem. But REST has always been a backend developer’s forte. Whereas with GraphQL, even frontend developers have started using it to develop the APIs etc. The learning curve with using GraphQL is far less, and the developer friendly tools have led to a sizable increase in the adoption of GraphQL.

The GraphQL ecosystem has plenty of amazing tools. One of my favorite is the GraphiQL explorer. With GraphiQL, you can type your queries to the API and get responses back from the server. The documentation is also available, along with live syntax and validation errors. Tools like these, make the GraphQL developer experience far ahead of REST.

We will learn about GraphQL tools in another post at a later time. Here is a link to some awesome GraphQL tools if you are interested in exploring them.

Conclusion

REST is a traditional approach and has been around longer. GraphQL is catching up and has gained a lot of momentum. Don’t think GraphQL is an option only for new products and new code. Even if you are working on legacy systems that use REST, you can still integrate GraphQL to fetch data from the legacy REST systems. This would help in improving the client layer. You can write queries to the new GraphQL server, which then talks to the legacy systems.

If you are already using GraphQL, leave a comment on what strikes you the most about it.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

A Beginner’s Guide to GraphQL

REST vs GraphQL - What's the best kind of API?

Securing RESTful API with Spring Boot, Security, and Data MongoDB



Originally published at https://programmingwithmosh.com