Should you use Hasura?
You can also read the post here
For those who don’t know, I work with Fountane and we are a creative studio that helps business gain digital presence or even technical presence.
This normally involves either auditing their existing websites for better seo and user experience, or even building web/mobile apps for them from the ground up.
This obviously requires a bit of work but a lot of clients are in the hurry to get into the market for various reasons that we might not be able to understand but a lot of projects that come to us have a really tight deadline and this is where Hasura came into the picture.
From Scratch REST APIs
We used to build APIs like any other firm, build optimized REST standard APIs and while this worked it was slow since a lot of the code couldn’t be reused (other than maybe the auth part) and writing CRUD for every model again and again was a slow process and often pushed the deadline a bit which was sub-optimal for a studio that was fast growing.
Loopback
For developers who have had similar problems , a lot of them moved to Nest, Loopback , other frameworks that try to replicate the Angular Arch where everything is pluggable to the original base and not very hard to do.
I used and liked loopback 3 for a project and it worked great. The generation of CRUD was no longer needed and I could use the Angular generated services from loopback to automate the SDK creation for API calling and everything but this went south when Loopback 3 announced EOL and Loopback 4 was a drastic change and little more learning curve than I’d like the team to go through.
I could’ve just forked loopback and maintain a personal copy for this but then loopback is not just the core repo, its the connectors, the additional pluggable modules , everything, that would be a project in itself.
The requirements and Hasura
Well, my buddy Gautam aka https://backend.engineer like the loopback arch and wanted graphql for the newer apps and we ended up deciding on hasura and trying it out for a project or two to see the mileage of the framework and Pandey was given the work to architect a monolith (webhook server and hasura, no web app here) for this.
A week or so later, this was done and ready to be transferred to projects that were still in the arch phase
At this point, we have 4 projects that use hasura and what you are going to read next is my review of whether you should use hasura or not and obviously the occasional knowledge transfer as to where it makes sense and where it doesn’t.
The good parts
These are simple and pretty much why people pick it up.
- Easy CRUD for all generated models
- A Web UI to handle most of the work
- Handles permissions, roles, and migrations for you
- Comes with the ability to construct actions / queries/ mutations for you
You can literally read about it from their website since that’s what they market and also the reason why we picked it up in the first place.
The pain points, or things I didn’t like
The list is purely based on my experience and things I wish could be improved and obviously I have better alternatives instead of this.
1. The Migration and Metadata System
While most of it is automated and it looks graceful and is atomic if done well, it’s not very intuitive and goes against the norms of migrations if you were doing it with something like knex but then that’s with every framework, like Loopback had it’s own way to handle table updates and migrations so I can be a little lighter on this.
The actual pain point though is that the migrations get overwritten very easily when 2 or more people are working on their local systems and this creates an issue since they can be timed to be the same they can conflict and there’s no way to find out what went wrong, this in turn breaks the metadata of the entire console and now you have missing permissions and actions. Post this, you will have to go through your git history to read through the metadata to find out what went wrong and also through migrations and manually merge this.
If the developer is good with SQL then modifying and merging these .sql
migration files shouldn’t be an issue but then I don’t see why I need a framework cause it does end up adding to the total work time and sometimes can take a lot longer than expected.
The other part is the structure of the metadata, while it’s a simple JSON that you can browse through, this can get super messy when the application get’s a bit bigger and it’s the worst when you accidentally mess up the permissions in the meta data.
2. No Dynamic value comparison in Permissions
Yeah yeah, I can send new headers with X-hasura-<variable-name>
and then use that for the dynamic comparison but that’s a super hacky way to get it done.
Beats the point of already sending all the needed data in the Payload and then sending it again in the header because the framework decided that it can’t add a $payload.id
in the permissions meta and and and, You can’t do the above without modfying your auth handlers to handle the additional dynamic variables.
This not only changes how people handle permissions but is also very limiting for a full fledged industrial application and if you have a super complex permission check, it’s easier to write a custom action instead of asking hasura to handle it cause it will require a dynamic comparision based on dependent outputs of other tables and that very hard to maintain, it’s unreadable , and you are better off just writing it as a custom action.
3. Closed Box model
You can say that , this is because I liked loopback a bit more so I expect hasura to be the same but I understand each framework has it’s own set of opinions and depends on the creator’s thoughts of how they want to build something and while I see why they did that, considering most of it is in Haskell and extending it would need knowledge of Haskell.
Though, being able to extend the model’s methods would actually align perfectly with how graphql works when you build one from scratch and also reduces the amount of permission handling that they have on the Web UI and instead be simple middleware functions that you can write based on the context of the query.
That would help maintain a smaller and more maintainable architecture compared to what it is now. The hasura arch was with the thought of having microservices in place and gateways that handle these microservices but when most of the app you are building requires a lot of logic and permissions then this closed box becomes counterproductive and you end up spending more time trying to figure out what goes where instead of actually getting done with the application.
Solution
I don’t have a concrete solution to match with this right now but if the CRUD and models is all that I wanted to solve, It would be better to setup Prima and Express Graphql (if you still use express) or use AdonisJS with apollo server or basically anything with apollo server or your language specific scratch graphql implementation.
This could be a combination of Python + Flask/Rapid API/DJango + GraphQL + ORM + CRUD Generator plugin (which you can find for most Setups at this point and it’s not hard to write re-usable CRUD handlers that replicate the actions for the ORM that you are using).
This gives you the ability to scale on the small arch and manage things while keeping control on what this can do. I can’t do that to hasura without picking up a new language, forking it and then changing all these.
Your opinion on the usage of Hasura might totally differ but to conclude
Should you use Hasura?
It’s not a bad framework at all, it just doesn’t suffice the requirements of our use case and the overhead of hacking into the problems that come aren’t worth spending time on when you are on tighter deadlines.
On the other hand if you are in for a quick way to the market with simple and trivial implementations it perfectly fits the usecase as you can reuse most of the work you did before into it very easily and most of it can be setup using interconnected docker setup’s so it’s pretty easy to replicate the environment no matter where you deploy it.
Though the same can be done if you create your own setup and that’s a lot more easy to maintain than a framework that you need to hack into to make things work (I made grator because the migrations would fail when moving into new systems and I wouldn’t want to keep making such tools just because the framework wasn’t handling it)