Hasura stands out as a formidable player in the realm of modern web development. Particularly for those projects that demand efficient, flexible, and scalable data management solutions. Its prowess in automatically generating CRUD operations, coupled with its robust handling of relationships and support for complex queries via PL/SQL functions, positions it as a highly productive tool for developers.
This blog post, instead of talking about how to set it all up; will take a look at the good, the bad, and the nitty-gritty of using Hasura for projects.
Have you ever wished talking to your database was as easy as ordering pizza? Welcome to Hasura. In the world of building apps, dealing with databases can feel like trying to solve a puzzle without all the pieces.
That’s where Hasura comes in, acting not just as a simple translator but as a powerful connector that lets your app chat fluently with your database, especially if it’s PostgreSQL (though it’s open to connecting other databases too). Hasura uses foreign keys to track relationships between tables, enabling easy use of these relationships within GraphQL queries. For example, if there is a base_organization relationship, you can include this relationship within a nested query to retrieve related data.
Hasura offers several advantages, including its ability to connect to multiple sources, an integrated ORM with UI for simple migrations, support for basic SQL migrations, and automatic creation of CRUD operations that can be customized with GraphQL. It allows you to define tables, such as the user table, which triggers the creation of corresponding CRUD operations like insert_user, update_user, and delete_user.
These operations can then be used in GraphQL queries and mutations, providing flexibility in defining your application’s logic.
Another benefit is that it has its official Docker image and can be hosted anywhere or in the Hasura Cloud which has other perks I won’t list here.
Finally, since it uses GraphQL, when using Typescript it is very easy to have typed requests since the generated schema will include all the types necessary, something that doesn’t happen with REST APIs.
I would say the biggest downside in my opinion is that since it uses GraphQL it’s very easy to execute the GraphQL queries directly in the frontend that can expose the mutations/queries to the client. It’s designed like that and the documentation encourages that, but not all graphQL should be exposed.
I use it with Next.js and our team instead uses the custom server approach and creates a custom graphQL schema to call Hasura from Next.js backend instead of directly the frontend. This allows us to check permissions and remove the graphQL schema from the client.
I wanted to mention that it didn’t support NoSQL but the latest development has MongoDB on beta.
Finally, it’s not as popular as other similar alternatives like Prisma.
What I like about Hasura is that it automatically creates all the possible CRUD operations and those can be customized with GraphQL. So I only have to define a table, for example I define the table user in a migration.
CREATE TABLE public."user" ( id serial4 NOT NULL, "name" text NULL, email text NULL, username text NULL, "password" text NULL, created_at timestamptz DEFAULT now() NOT NULL, updated_at timestamptz DEFAULT now() NOT NULL, is_enabled bool DEFAULT true NOT NULL );
So now Hasura will track the table and will create an insert_user, update_user, delete_user
and user GraphQL mutations/queries that include the basic CRUD operations. To use them it’s necessary to write customizations like these:
query ExampleQuery { user(where: {is_enabled: {_eq: true}, password: {_is_null: false}}) { email id is_enabled last_login name } }
Hasura will use the foreign keys to other tables to create graphql relations and track them to use them easily in the custom mutations/queries like this.
Let’s suppose there is a table organization and Hasura tracks it via the base_organization
relationship. So this allows to use relationship inside the where statement and just by including the relationship in a nested query it adds it in the select.
query MyQuery { user(where: {base_organization: {name: {_eq: "devto"}}}) { email id is_enabled last_login name base_organization { name } } }
For more complex queries, Hasura supports writing plain PL/SQL functions, allowing developers to write any necessary SQL without having to learn a new ORM syntax. This provides flexibility in handling project-specific requirements.
Here we add a computed property that can be exposed as a GraphQL property.
CREATE OR REPLACE FUNCTION computed_full_name(user_row "user") RETURNS TEXT AS $$ BEGIN IF user_row.first_name IS NOT NULL OR user_row.last_name IS NOT NULL RETURN COALESCE(user_row.first_name || ' ', '') || COALESCE(user_row.last_name, ''); ELSE RETURN COALESCE(user_row.name, ''); END IF; END; $$ LANGUAGE plpgsql STABLE;
Inside these functions we can write any custom SQL needed for the project, for non computed properties a new table will be needed so Hasura can map the return type but there is no limit in what the SQL can have.
We can check roles and check that they can only query their own data, known as ACL (access list control). While some other frameworks are very good at this, Hasura needs a lot of configuration for this. Let’s see an example:
whitelist.add({ document: AddSurveyTranslationsDocument, check: hasOrganizationAdminGrant }); whitelist.add({ document: GetManageAssignmentsDataDocument, authorize: ({ appUser, variables }) => { // Enforce that from front-end, user must query in his own behalf only return variables?.managerUserId === appUser.id; }, allowedRoles: [HasuraRole.USER, HasuraRole.ADMIN] });
As the tech industry evolves, finding and engaging experienced and cost-effective software developers remains one of the biggest challenges for companies. According to the U.S. Bureau of Labor Statistics, software developer demand is projected to grow by 22% by 2029 — much faster than most other professions. This means that recruiting top talent is becoming…
What’s Organizational Culture? Is it the mission and values of a company? Its benefits? We could say that all of this is part of and makes up the culture, but at BEON.tech, we believe that the most important thing is our people. Felipe Zacani, Node.js engineer from Brazil working with AutoFi, describes BEON’s culture as…
Working remotely and exploring remote jobs for non-U.S. residents as a developer in Latin America can be exciting and challenging at the same time. To ensure a successful collaboration, it’s essential to establish a good impression from the beginning and adopt effective work practices. We know that it’s a big leap for your professional careers…