GraphQL isn't that amazing

I really didn't think it would come to having to explain this but people think
that GraphQL is the holy grail at this point and that REST isn't needed anymore.

I can just say "You're wrong" and let it be or I can get into a details and
bring sense to the standard. Let's do the 2nd one since I haven't ranted in a
while.

Why does it exist?

This is the specification for GraphQL, a query language and execution engine
originally created at Facebook in 2012 for describing the capabilities and
requirements of data models for client-server applications

Source: https://spec.graphql.org/October2021/

So, facebook needed a way to have the client and server be able to communicate
the data model. HTTP was still the protocol of communication so they were
limited to GET and POST requests but they wanted the client to be able to talk
to the server and explain itself better.

Here's what people imagine it to be.

Before GraphQL

client: /users
server: Here's all the users, go bonkers
client: Um, i also need the profile pics...
server: the backend developer didn't add it in the response, sorry, make a
request to /users/:id

After GraphQL

client: /graphql => query users { users {id name email} }
server: ...
client: Um, i also need the profile pics... so
query users { users {id name email profile_pic} }
server: ...

and honestly, I'd blame the blog posts that actually make it seem like this, but
just adding graphql doesn't just make it easier.

The above REST implementation would be considered bad talk to the backend dev
and get the field added? how hard is that?

The backend developer can still make the above fail by not including the
profile_pic in the attributes that I get from the db

And now, you get an empty string in the profile_pic everytime.

BUT I CAN GET RELATIONAL DATA!!?
The backend developer still has to define the types for it and include it in the
response. The work for there hasn't been reduced, it has instead been increased
since the types are to be defined for it.

  1. Define types for the response, and request
  2. Define types for the relations
  3. Define types for the models of the DB

I don't see any reduced time here

So, Should we use it or not?

Well, every developer who's tested quite a few stacks would say, it depends.

But depends on what?

Here's a few things that graphql makes easier for a backend developer

  1. Request Model Validation is done for you, since you define it for input.
  2. Response fields are auto documented due to your types so you save time on
    internal documentation. (external documentation still needs work and
    honestly, I wouldn't want that automated)
  3. In most implementations, you don't need to worry about routing anymore since
    it's all just one handler processing the DSL. If this sounds like RPC then
    don't be shocked, it did take inspiration.
  4. Provides a way to also handle realtime setup because you get subscriptions
    support from most graphql engines

Now, let's get to the client side of things, or how the frontend developer's
job is made easier

  1. Since model definitions are passed through the schema, you get type
    definitions that graphql clients can use to provide typesafety a.k.a
    browsing the documentation is reduced to just looking for exposed operations.
  2. Selective data, but this isn't an immediate thing, you have to learn to
    write fragments . Thus, giving you the ability to include additional fields
    based on the screen/view/page you are working on. Just creating an SDK
    wrapper on top of all fields or selective fields doesn't really make any
    difference. You reduced the network load but increased the memory usage of
    the app which well, is not really an advantage.

Eg:

# this doesn't really make it any better
query users {
  users {
    id
    name
    addresses{
        id
        street
        state
        country{
            id
            name
            shortCode
        }
    }
  }
}


# you'll have to learn to divide them so that
# they can be composed so you can selective get
# the needed data

fragment UserFields on User {
  id
  name
}

fragment AddressFields on Address {
  id
  street
  state
}

fragment CountryFields on Country {
  id
  name
  shortCode
}

query userBaseDetails {
  users {
    ...UserFields
  }
}

query userDetails {
  users {
    ...UserFields
    addresses {
      ...AddressFields
      country {
        ...CountryFields
      }
    }
  }
}

and well, ideally I'd only create a query when it's needed more than once with
the same fields, else I just use the field fragments based on the view's
requirement.

Now, the client get's the exact amount of data that it needs on that exact view
while still being able to scale.

Creating a single query with all fields being used everywhere basically feels
like REST that was written on the frontend, beats the whole argument of
"fetching only what's needed"

Fragment writing can be a pain and redundant so shameless plug but you can use
gqlfragments to generate them for
you.

  1. The 3rd advantage is not having to deal with url suffixes, and this is both
    an advantage and disadvantage. Advantage, when it comes to the
    development of the app as it reduces the amount of code you write for network
    requests and disadvantage when you have to go through 100 /graphql
    requests in the network tab to find out which one is that's making an invalid
    data call and then look for the operation that it was passing, can get quite
    irritating

There's a few more but none that actually make any big difference.

Better than REST?

Uh... in a way, yes.

But most of what's above can be done in REST

  1. Selective fields? Easily implemented with middlewares
  2. Model validation? There's tons of library for that
  3. Url suffixes? OpenAPI / swagger => sdk generator. Done.
  4. Type Safety? If you are working with a language that's statically typed, this
    shouldn't be hard to do. JS has trpc which does this with shared types and
    reflections.You can just have a types package in your modern monorepo to do
    it for you.

I've left realtime setup, because I'm sure there's enough websocket information
online.

You'll have to add routing for REST which is definitely redundant but it's okay,
you can spend 10 extra seconds to define a route definition.

BUT THAT'S SO MUCH WORK!? True, REST implementations require quite a bit of
setup to get everything working but so does GraphQL. If it's just about how much
time it'd take to start a http server that can respond to a /ping request.

I'm sure you can imagine that a simple http REST server would take me 30 seconds
and graphql would need a little more than 2-3 mins when typed out.

const express = require("express");

const app = express();

app.get("/ping", (req, res) => {
  res.send("pong");
});

app.listen(3000, () => {
  console.log("listening");
});

Okay, took 43 seconds...

let's try go lang

package main

import (
    "fmt"
    "net/http"
)

func main(){
    http.HandleFunc("/ping",func (w http.ResponseWriter, req *http.Request){
        fmt.Fprintf(w,"pong")
    })
    http.ListenAndServe(":3000",nil)
}

about a 1min

You're telling me, you'll be able to define a resolver, define it's return type,
add in the graphql engine imports, implement the resolver and the processor then
add in the http server that reads the request, passes it to graphql in the same
time? Nope. Not happening.

Anyway, not here to bash GraphQL. wanted to clarify what the advantages are, and
cleary the above 2 examples are just jokes. I'd have to write much more code to
get the same features that the graphql engine would give me.

  1. Validation
  2. Doc generation
  3. Playground etc, etc

so yes, the time spent to setup GraphlQL is worth it, it is better than any
simplistic REST implementation but no there's no winner here, it's a usecase
thing.

It depends on how much work you're willing to put up for the setup. I did
write about the amount of work it took to find a decent GraphQL working solution
for work, which you can read about.
Full Stack Development with GraphQL in a Digital Studio

REST is easier to iterate over, without breaking the entire engine and you can
find mature sets of tools to help that backend be more stable and making an
argument that "the client decides the response" is an advantage? Dude, the
backend developer can still change the response type definition and you are done
for. You need to collaborate to get the app out, just one of you aren't working
on it.

To other writers, stop using bad REST API implementations as examples for moving
into GraphQL, I can write bad GraphQL API's as well