There are quite a few misconceptions when it comes to graphql. It cannot be cached on http protocol level, it has to return 200 code even when there are errors, it kills fluffy kitten every time you make a mutation.
In this short post I would like to address one of them in particular. No not the one about the kittens.
🍄🌼🌈🎮☕🚲💻🪙🐩🥓🛻🇺🇸♓.eth@yesiwebtoI'm getting to do GraphQL today at my new job!
I've been reading about it for years, but never took the plunge to try to actually use it. Having used REST APIs for years, I like gql in theory. But I'm also a pragmatic minimalist so we'll see if it's too much overhead.16:14 PM - 03 Sep 2021
Alex LoukissasHot take: #GraphQL is just REST where instead of controllers you write resolvers (same thing), with an API/data schema (good), and really, really fat clients. I'm sure it has its use in big projects/teams, but for small projects it's just tremendous overhead.18:04 PM - 18 Sep 2020
François Vaux@madx@nblanco_fr @vercel Well I'll have to disagree there. I think REST is fine in 95% use cases (probably more). GraphQL adds another layer of tooling, overhead and overall complexity.06:41 AM - 03 Jul 2020
Let's analyse and dissect what these developers might be talking about.
Overhead on the Consumer side
Sure, with graphql you need to send an exact list of fields you want back. If your model is complex and it has lots of fields, this does indeed introduce extra bytes and extra time writing the API request.
This "overhead" only exists if you're accessing the API from curl.
Every graphql API should come with graphiql/playground bundled. These tools complete the query for you, so there is little to no developer time lost.
If it doesn't come bundled with the API you can run a variety of graphql clients on your end.
For example graphiql does it here.
Hence I came to a conclusion that it's not this overhead that these people are talking about.This is too trivial and solvable with tooling everyone uses by default. This cannot be it.
Overhead on the Server side
This one is harder to crack. Is this actually a myth? There are myriad ways to write a backend in both of these. In order to prove I knew I had to get my hands dirty.
I was always a fan of DRY, not DRY nazi, just a fan. So I've been actually always searching for less verbose ways to write APIs, ever since I started years ago.
In the last few years I've gravitated toward stacks centered around fastify. So let that be the http server base for our comparison.
I don't think there are more succint ways to write a documented REST api other than fastify and fastify-swagger. The way fastify-swagger leverages validation schema to produce the docs is quite awesome. It reminds me of a a poor man's thing which starts with a capital "G" and it's killing kittens.
Similarly, for the Graphql camp, I don't know anything less verbose than Typegraphql and mercurius.
Mercurius-fastify plugin has the best defaults of any GQL server and performance on whole different level compared to apollo-server.
So I've taken a bit of time today and written a single CRUD endpoint for a very simple blog. There is no authentication, no rate limiting, no caching, nothing extra-just a pure bussines logic for CRUD over one DB table.
What I do implement in both is validation and documentation as we need to have feature parity for a fair comparison.
For ORM I chose prisma, as it offers awesome generators to spare my lazy ass from writing API schemas manually.
For the DB we just use sqlite.
What was the result?
See this repo: https://github.com/capaj/node-rest-vs-graphql
These endpoints are implemented:
- query for blogpost with filtering by from and to dates
- query to fetch a single blogpost
- mutation to create a new post, update existing one and delete a blogpost
Just for this very simple API, REST adds 21 extra lines.
I would welcome any PR regarding simplification of the REST api, because I may have missed something. Maybe there is some magical way how to have validation and documentation without all that work. Maybe I just haven't learned it yet. I am just a junior dev 4life.
I really wish there was an easier way to properly do REST apis in node.js. Personally I'll be sticking to typegraphql and mercurius.
Keep in mind that for a more complex api-where you have deeply nested relations of entities, REST becomes even more unwieldy. Graphql is natural for representing data with lots of relations allowing the consumer to nest their queries deep. In leaf resolvers you always have access to a parent when resolving a child-you can often use this to simplify your BE code.
These practices of structuring endpoints exist in REST as well, but it's all manual. You actually need to write bunch of middleware to get it to work.
Final note: please if you see anyone on twitter talk about how Graphql has implementation overhead compared to REST, do send them this link: https://github.com/capaj/node-rest-vs-graphql/pull/1
Top comments (2)
"Sure, with graphql you need to send an exact list of fields you want back." Not true, depends on how resolvers are implemented, you can have some default set of fields which you dont have to ask for every request of particular entity.
Interesting. Haven't seen this in the wild.
You certainly can make some resolver return JSON scalar and in that case you cannot even pick the fields, but I only use that for data of unknown shape.