GraphQL

on their website

Developed by Facebook in 2012

for their Mobile Apps

Open sourced first spec 2015

Graphql.js

Its a  Query Language built on top of REST

but way better

Everything is a single POST call /endpoint

Query is sent as post body

query {
 users {
   name
 }
 likes {
   id
 }
}

Sample Call

curl 'http://localhost/graphql?' \
-XPOST \
--data-binary 'query { users: { name } likes: { id } }'
query {
 users {
   name
   bio
   pic
   likes: {
     id
   }
 }
}

Sample Call

Use Case 1

Just Make Another Call

GET /users
GET /likes/1
GET /likes/2
GET /likes/3

No of Calls: 4

REST

3

  Prathik

4

    Saurabh

5

     Armaan

When user list and likes are separate calls

query {
 users {
  name
  profilepic
  bio
  likes: {
    id
  }
 }
}

No of Calls: 1

GraphQL

3

  Prathik

4

    Saurabh

5

     Armaan

Use Case 2

Just Rename That Field

[{
  name
  profilepic
  bio
}]
[{
  name
  pic
  bio
}]

Code Change Everywhere

REST

When API renames a field

query {
 users: {
  name
  profilepic: pic 
  bio
 }
}

No Code Change

GraphQL

Use Case 3

Just Play Around

Its takes time to write documentation

REST

Its painful to keep it up to date

REST

Its tough to agree on one tool

Provides documentation free of cost

GraphQL

Swagger, Postman, GitBook all in one

GraphQL

Use Case 4

I Don't Need That

REST

GET /users
GET /users-without-pic

or 

GET /users?includepic=false

  Prathik

3

  Saurabh

4

Armaan

33

Loki

300

3

  Prathik

4

    Saurabh

When you want to skip a field

query {
 users: {
  name
  bio
  pic
  likes: {
    id
  }
 }
}

GraphQL

query {
 users: {
  name
  likes: {
    id
  }
 }
}

  Prathik

3

  Saurabh

4

Armaan

33

Loki

300

3

  Prathik

4

    Saurabh

Client needs to understand single auth mechanism

Plus all advantages of single endpoint

Basics

Schema

Server Side

Three basic things

Query

Mutation

Subscription

Query

type query {
  users: [User]
  user(id: Int!): User
}

Types

id: ID
name: String
age: Int
isHuman: Boolean
amount: Float

Scalar

enum Gender {
  MALE
  FEMALE
  OTHER
}

Enum

location: [Location]

Lists

gender: Gender
Type User {
  id: ID
  name: String
}

Object

age: Int!
location: [Location!]!

Not Null

users(name: String): [User]
user(id: Int!): User
inteface Message {
  id: Int!
  msg: String!
}

type SMS implements Message {
  id: Int!
  msg: String!
}

Interfaces  

type Mutation {
  createMsg(input: string): Message
  updateMsg(id: ID!, input: string): Message
}

Mutation  

Fetching Data

Client Side

query {
 users {
   name
 }
 likes {
   id
 }
}

Recall: Sample Call

curl 'http://localhost/graphql?' \
-XPOST \
--data-binary 'query { users: { name } likes: { id } }'

Query

users {
  name
  age
}
{
  data: {
    users: [
      {
        name: 'Prathik'
        age: 7
      }, {
        name: 'Saurabh'
        age: 7
      }, {
        name: 'Armaan'
        age: 7
      }
    ]
  }
}

Query

users {
  name
  age
}
query {
  users {
    name
    age
  }
}
=

Arguments & Variables

user(id: 7)  {
  name
  age
}
query Query1($id: Int) {
  users(id: $id) {
    name
    age
  }
}
{
  id: 7
}

Fragments

user  {
  ...userFragment
}
likes {
 id
 user: {
   ...userfragment
 }
}

fragment userfragment on User {
  name
  id
}

Alias

user {
 id
 username: name
}
organiser: user(id: 7)  {
  name
  id
}
admin: user(id: 8)  {
  name
  id
}

mutation

mutation Query1($user: User) {
  createUser(user: $user)  {
   id
  }
 }
{
  user {
    name
    bio
  }
}

Code

Demo

Gotchas 1

Inception

type Query {
 likes
 users
}

type Likes {
 id
 user: User
}

type Users {
  name
  pic
  bio
  likes: [Likes]
}
query {
  users {
    name
    likes {
     id,
     user {
      name,
      likes {
        id,
        user {
          id
        }
      }
    }
  }
}

Schema

Client Query

Its like query inside query inside query

Design your custom Query Complexity Rule 

Example:
Every {               = 5  point
Every Page            = 10 points
Every Nesting         = 15 points
Max Allowed           = 60 points

 

Solution

Gotchas 2

Problem Transferred 

GET /users
GET /likes/1
GET /likes/2
GET /likes/3

REST

N + 1

query {
 users: {
  name
  likes: {
    id
  }
 }
}

GraphQL

N + 1

1

Database still collapses

Use a Query batcher

N + 1

1 + 1

Solution

Gotchas 3

Overwhelmed 

Traditional Rate Limiting not suitable 

REST

 

Max RPS = 2000

Rate limiting is server's job not of GraphQL

Use a combination of

Rate Limiting  & Query Complexity (QC)

REST

 

Max RPS = 2000

GraphQL

 

Max RPS = 500
Max QC  = 60 

Solution

Links

Namaste 

Thank You

GraphQL

By Prathik S

GraphQL

  • 371