GraphQL:

y tho

Conclusion at the Start

GraphQL is kind of like a pick up truck.

If you research them a little and ask yourself, "why would I bother  to fit this gas-guzzler in my garage?"

Then it's probably not for you.

On the other hand, if you need a pick up truck, you'll know you want it half-way thru it being explained to you.

My Assumptions About You

  • Have made or used a REST API at least once
  • Briefly looked over GraphQL's website
  • Know generically that GraphQL is meant to replace REST APIs in some way
  • But you don't quite understand why you'd want to, cuz REST APIs like...work just fine

Hello World GraphQL

  type Query {
    hello(name: String!): String
  }

Schema

query {
  hello(name: 'Robert')
}

Query

{ data: { hello: 'Hello Robert!' } }

Response

src (with edits): https://graphql.org/graphql-js/

Demo Time

What is it trying to solve?

  1. Number of client roundtrips
  2. Amount of data returned
  3. Minimize client-side data manipulation
  4. Documented and functional schema parity

src: https://medium.com/@asimnazir.uet/beyond-rest-with-graphql-12cfc4e7a951

#1: Round Trips

src: https://medium.com/@asimnazir.uet/beyond-rest-with-graphql-12cfc4e7a951

#1: Round Trips

#1: Round Trips

Github example

  • Get your first 10 repos
  • Get their owners and their first 2 repos

#1: Round Trips

REST API

GET api.github.com/user/repos?per_page=10
GET api.github.com/users/{username}/repos?per_page=2

1 call

Write code to extract the owners of each of those repos and then make....

up to 10 calls

#1: Round Trips

{
  viewer {
    repositories(first: 10) {
      nodes {
        name
        owner {
          login
          repositories(
            first: 2, 
          ) {
            nodes {
              name
            }
          }
        }
      }
    }
  }
}

GraphQL

1 call

REST

2 rounds of calls: >400ms
11 calls in series: >2.2s

GraphQL

1 call: ~200ms

#1: Round Trips

assuming ~200ms per call

#1: Round Trips

src: https://michaellutjen.com/blog/17-updates-to-decrease-bounce-rate/

#1: Round Trips

👈
Real footage of a Frontend Engineer demanding you nest this REST API endpoint now

#1: Round Trips

Deeply nested queries are bad for many reasons.
Among them: it's impossible to anticipate everything you'd want. You can't keep shoving in _everything_ related to _everything_ else in _every_ endpoint.

 

#2: Amount of Data Returned

query { 
  viewer { 
    repositories(
    first: 100
    ) {
      nodes {
        name
      }
    }
  }
}

Github, first 100 repos logged-in user

api.github.com/user/repos

GraphQL Query

REST Endpoint

#2: Amount of Data Returned

Github, first 100 repos logged-in user

GraphQL Query

REST Endpoint

171kb

1.8kb

That's 100x payload savings.

#2: Amount of Data Returned

If this query is made 1000 per second, at the end of a month of activity....

GraphQL Query

REST Endpoint

443,232 GB/mo

AWS

Egress Pricing
~$0.09/GB

$39,890/mo

4660 GB/mo

$410/mo

171 kb/call

1.8 kb/call

#3: Minimize Clientside Manipulation

Getting data in a shape that's useful to you in the first place, and not needing to reshape it to use it.

#3: Minimize Clientside Manipulation

Github example

  • Get your first 10 repos that are forks.
  • Get their owners and their first 2 repos for each of them that they own (aren't forks).
  • Order their repos by highest number of stargazers first

#3: Clientside Manipulation

{
  viewer {
    repositories(first: 10, isFork: true) {
      nodes {
        name
        owner {
          login
          repositories(
            first: 2, 
            isFork: false, 
            orderBy: {field: STARGAZERS, direction: DESC}
          ) {
            nodes {
              name
            }
          }
        }
      }
    }
  }
}

GraphQL

#3: Clientside Manipulation

{
  "data": {
    "viewer": {
      "repositories": {
        "nodes": [
          {
            "name": "django-filter",
            "owner": {
              "login": "worthwhile",
              "repositories": {
                "nodes": [
                  {
                    "diskUsage": 227,
                    "name": "django-herald"
                  },
                  {
                    "diskUsage": 8,
                    "name": "geo-bound"
                  }
                ]
              }
            }
          },
...snip...
        ]
      }
    }
  }
}

#3: Clientside Manipulation

REST API

GET api.github.com/user/repos
GET api.github.com/users/{username}/repos

1 call

The REST API has no "is_fork" param. So write a bunch of code to page over all of your repos, filter out those in JS that are forks, and from that list extract out the owners of each of those repos...then

up to 10 calls

The REST API has no "is_fork" param, nor an order by for stargazers. So write a bunch of code to page over all of their repos, filter out those in JS that are forks, and then resort the remaining by stargazers. Then merge the two data structures together....

#3: Clientside Manipulation

REST API

I ain't doing all that just for a demo ya'll.

#4: Documented and Functional Schema Parity 

The documentation matches what's happening in when you use it because the documentation is the real thing.

Complaints about GraphQL

  • It's complex
  • It's overkill
  • It's incomplete

Complaint: much more verbose and harder to use for simple cases

Complex

My Opinion: a bit hyperbolic. It's not always much more verbose, and I'm sure I can find longer REST queries. But yes, it is more verbose on avg (see next slide for example).

Once you learn GraphQL. You've learned it entirely. Unlike REST which has different flavors--even within the same API provider.

REST

GraphQL

Complex (verbosity)

 curl -i  
   -H "Authorization: token shhh" 
   -X POST 
   -d '{"query":"{ viewer{ repositories(first: 100){ nodes{ name }}}}"}}' 
   https://api.github.com/graphql
 curl -i  
   -H "Authorization: token shhh"
   https://api.github.com/user/repos

Overkill

Complaint: People usually don't need all this. REST usually solves their issues. It's simpler to understand and implement from the server side.

 

My Opinion: you're right. You might not need this. Frontend devs who tried both GraphQL and REST seem to prefer GraphQL, because they can rely on it being far more consistent of an experience.


If you're a full stack or backend dev, this may all seem like a whole lot of work and complexity, because it is. 

Incomplete

Complaint: It doesn't even solve everything you need to do like error messages/codes, authorization, file transfers, or even pagination!


My Opinion: you're somewhat correct. It mentions many of those things, and gives advice on how to solve them. But you're correct that it doesn't solve them in their spec. But for that matter, REST doesn't have a spec either. It just has conventions/expectations so in that sense it's no worse than REST.

Conclusion Again

GraphQL is kind of like a pick up truck.

 

If you look at it and ask, "why you'd want to fit this gas-guzzler in your garage". Then it's probably not for you.

If you've now seen what it can give you, and you're like, "OH, I CAN TOTALLY USE THAT!" Then it's probably for you.

Conclusion (Secret)

Conclusion (Secret)

Software isn't as exclusive or strict as buy a car or a pick up.

Every company large enough to have a public GraphQL API to my knowledge also maintains its REST API.

 

Conclusion (Super Secret)

Why do they have both?

Their GraphQL API usually is just calling their REST API under the hood. 😉

Aaaaand it's not a big deal for them, because for service-to-service calls they're usually doing REST or RPC anyway....but that's a talk for another day.

Robert Roskam

Organizer for

@raiderrobert 

twitter | github

Work at

GraphQL: y tho

By Robert Roskam

GraphQL: y tho

  • 162