Overhead of using REST instead of Graphql with node.js
Jiri Spac
Posted on February 4, 2022
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.
Let's analyse and dissect what these developers might be talking about.
Overhead on the Client side
As a consumer of graphql APIs 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 DX complexity writing the API request.
This "overhead" only exists without tooling.
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. On the contrary developers can explore the API at the same time as they query.
Even when it doesn't come bundled with the API, developer can run a variety of graphql clients on their 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.
REST
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.
Graphql
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.
One last reason for me to avoid REST is that I am quite bad at remembering to do something when I am not forced to do so by an automated system. If I was writing REST apis, I would most likely need a colleague to remind me to add that optional validation in every odd code review. This is potentially solvable in fastify type definitions. I think it's not likely it will ever get implemented. Fastify is primarily a javascript framework and the type defs are manually added just for consumers.
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
Posted on February 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024