Hi HN! Super happy to announce the first open-source release of the Hasura GraphQL engine.
This is a standalone service that gives you GraphQL on Postgres. It comes with fine-grained access control that can integrate with any auth provider. It can also work with any existing postgres database as is, and allows you to expose select tables/views across your postgres schemas over GraphQL.
Hi, I'm one of the core contributors to the project.
Hasura and Prisma have very different approaches and end-goals at the moment.
TL;DR:
Very simply put, Hasura is postgres first and adds an access-control layer to make it possible to query from the front end directly.
The longer version:
Prisma is intended to be a GraphQL ORM to Postgres (and several other databases with a common API) whereas Hasura is more database first and intended to let you leverage Postgres features over GraphQL.
Hasura comes with and lets you use any postgres migration system and then gives you GraphQL on top of it. This is what allows Hasura to give you GraphQL over any existing Postgres database and application even.
Hasura also comes with an optional access-control layer that makes it feasible to be used by frontend clients directly. This access control is inspired from postgres's RLS but does not depend on or use postgres RLS and can be coupled with application logic/auth.
> Prisma is intended to be a GraphQL ORM to Postgres
Sorry to be hijacking this thread, but how would you say Prisma compares to something like Graphene (with an appropriate ORM adapter). I've only used Graphene with Python and the SQLAlchemy adapter, but it sounds pretty similar? Is Prisma typically used as the only ORM in project, or is it used in conjunction with some other ORM?
I think you should be able to use it alongside SQLAlchemy if you manage your schema through Prisma. Someone from Prisma team should be able to give you a more thorough answer.
You should think of Prisma as the data layer for your applications. If you look at large tech companies who are typically ahead of the status quo for how to build applications, then you see that there is a trend to move away from traditional ORMs.
Twitter has a service called Strato that manages data access for all their services. Facebook has TAO that serves a similar role. Prisma is an open source implementation of that pattern.
If you are building a GraphQL API using for example Graphene, then you could use Prisma as your data layer, but Prisma can also be used in non-GraphQL applications.
If you are using the Nodejs implementation, then you can take advantage of schema delegation to simplify the implementation of your resolvers. The GraphQL ecosystem is still evolving, so these capabilities will come to more languages in the future.
So in short - Prisma replaces SQLAlchemy, not Graphene. Hope that provides some clarity :-)
Thanks for releasing such a project. Your website is really well done, it immediately made me want to dig in the tech, congrats !
PS: as a sidenote and since i'm sure you'll get the question a lot : when i saw it was coded in haskell i was a bit nervous, but at the same time a bit more confident this wasn't another junior-level spaghetti code base.
Very similar projects ! The emphasis of Hasura is to make it seamless to work with existing databases.
The primary difference is how authorization is handled. In Postgraphile, you map your application roles to Postgres users and define policies using Postgres's RLS. With Hasura, you define rules on roles (similar to Postgres's RLS) but it integrates into your existing auth system using webhooks.
Would you mind expanding on this a bit? It seems HGE makes a call to a webhook for every GraphQL query/mutation [1]? This sounds rather expensive to me. Thanks!
We're adding support for JWT soon too which should prevent this overhead for applications that support JWT. But basically the idea here is to be equivalent to session cache hit.
Another deployment pattern is to make everything go through an API gateway which would usually do the auth resolution for all microservices, and thus can set the dynamic variables required for access control for HGE directly too. In this case, auth-webhook is disabled.
Another salient difference (and, for me, a deal-breaker): PostGraphile exposes user-defined functions in the GraphQL API, making it possible to define application logic and build a complete service without recourse to any other server-side technology.
This looks great! Is there any interface for extracting encrypted columns through this? For example, decrypting fernet encrypted values, given the key?
What I'm not seeing is how do you envision enforcement of complex business rules when using this API. Examples (silly, but you get the idea):
- The price is only visible for projects of type "whatever".
- The price may only be updated when it is not closed (closed_date is null)
- The project is only visible on mondays
The other point I don't see is how do you expect to trigger side-actions when changes are made. For instance:
- Send an e-mail when a project is created
- Call a webhook when a post is modified
Finally, and this may be from my lack of expertise with GraphQL, how do you deal with recursive data structures? For instance, how would you store and fetch a tree of categories?
For the latter, GraphQL itself explicitly forbids recursivity [0], as it's impossible to guarantee that in all cases the data isn't infinitely recursive, especially with cyclic queries, which could lead to a denial-of-service. Postgres has its own support for recursive queries [1], however you'd need to strap a pagination layer on top in order to make it work with GraphQL.
You can write fairly complex rules with the access control layer ! The first two conditions are possible (except for the project is only visible on Mondays).
allow select on rows which satisfy this property:
{ "project_type" : { "_eq" : "whatever" } }
allow update on rows which satisfy this property:
{ "closed_data" : { "_is_null" : true } }
The idea is simple, we provide a boolean expression based access control layer which can use variables from headers. When you can't specify it using the access control layer, you can write this in your own graphql layer and schema stitch with hasura. So you only have to write what is not possible with the access control layer.
> The other point I don't see is how do you ...
You can use the tooling around Postgres ! You can create an `ON INSERT` trigger on the table and listen to these events.
We're launching something very cool in the subscriptions/event-source to solve these kinds of problems. We also have 2 nice projects that work independent of the graphql-engine to help with change subscription on postgres (skor[1], pgdeltastream[2])
For "access control layer" to work in the general case we need to be able to code it in a real programming language, no? Or are you going for something one-size-fits-many like Sharepoint?
> u can write fairly complex rules with the access control layer
Oh, I see. As a suggestion then, many business rules are not tied to roles. You may want to look into some "always enforced rules" or something like that, to avoid having to repeat these rules for each role (and the maintenance nightmare this entails).
> your own graphql layer and schema stitch with hasura
Again, I'm not versed in GraphQL in general, so this is from my ignorance. Maybe you could provide some example/tutorial on "stitching your own GraphQL apis with hasura" (your other examples, posts and tutorials are awesome btw!).
> You can use the tooling around Postgres
Fair enough. I've always found a bit hard to properly manage and test these native features (much harder than managing/testing pure code), but it is a sound solution nonetheless. Maybe you want to hint to these other projects somewhere in hasura's docs (I've checked them and couldn't find it, but maybe I'm just blind/didn't look hard enough).
Again, awesome project and good answers. I can't stop going through possible pet-projects to try this out soon! :)
> The price is only visible for projects of type "whatever".
Tangentially, this one's shockingly common and not something I'd consider silly. Many manufacturers obligate their distribution partners to market only certain prices in order to keep pricing expectations for a certain product at a certain level.
I suppose this can be done with row-based security if you are willing to mirror/maintain this in Postgres and/or fork the query engine to issue them under the right roles. There was a talk at PG Day UK 2018 about this but there are no performance benchmarking results available AFAIK.
As to triggers, you can totally do this with event sourcing in triggers, so when something is modified you write a row to the audit table, and you use another process to read from it and do the right thing, etc.
First glance reaction: Awesome, just the thing I need.
Then I saw the fine print: AGPL. Haskell.
The thing might be awesome, but the combination of the legal risk from AGPL (very little legal precedent for AGPL, especially outside the US, so the real legal implications of the license are very murky) and maintenance risk from Haskell (finding good Haskell developers is hard, and the learning curve is brutal), makes it a lot harder to choose.
Hm...Haskell was an important initial choice for us because of our team's comfort with the language and also because it's neat to implement parsers and compilers. The Hasura engine is essentially a GraphQL to SQL compiler :)
I'm not sure I understand your point about AGPL? Do you have the same issue with the MongoDB license and would hesitate to use Mongo because of their AGPL? Why is this different? Just curious, would love to understand where you're coming from!
I’m sure Haskell is great, just saying its a bit of a risk to add to your stack if you don’t already have Haskell developers in house.
That, and the AGPL issue are both more important in this case (compared to MongoDB), because of the position in the stack that Hasura GraphQL Engine (HGE) would have. In the MongoDB case, we would almost always have an application server between Mongo and the GraphQL client, where custom business logic could be implemented, so Mongo can be treated as an external system whose source code we do not need to modify (like PostgreSQL in the case of HGE).
In case of HGE, the GraphQL client would talk directly to HGE, and thus any customisation would most likely need to happen inside HGE, whether by plugins or patches or whatnot, making it tricky to avoid having to open source your custom business logic (as well as probably having to write it in Haskell).
We didn't intend for Hasura to be something like a boilerplate that you would modify. Mostly because it's harder to work with upstream changes when you work with OSS software like that unless it's an explicit library type dependency. What OSS service type component do you use (know of?) that is used in this way?
Currently, we encourage users to use GraphQL schema stitching to customise their GraphQL schema/resolvers treating HGE almost as an external GraphQL service.
I see. Maybe I’m too much of a pessimist, but I imagine most products would need custom server-side business logic, and that business logic would also need to talk to the database. So I guess you could put your own GraphQL server in the middle and just proxy some queries to Hasura and answer others with your own custom code.
But if you’re already building a separate GraphQL server with database integration, the business case for HGE is weakened, since you might as well build the same logic in the other system.
GraphQL is interesting although it doesn’t appear to be answer to designing better APIs (poor modularaization, monitoring, and tooling come to mind). “Mutations” look to be an afterthought, and schema/ui are not impressive either.
Above plus companies tripping hard to monetize tooling around something that you get completely for free with REST...
Even as UI engineer I don’t get the appeal of it - state, caching and all the “performance” tuning make it too complicated.
I am very hesitant to couple the business logic of any application to the transport layer (GraphQL) or the persistence layer (Postgres) for that matter.
Your reply suggests you either couple everything or nothing. It’s more nuanced than that. Everything is a trade off. With that said,
it looks like this library will position itself in the center of your architecture — and I would be very hesitant
to do that.
Of course anyone should be hesitant to over-model the business domain in any part of the application including the database, but the entire reason of existence of the RDBMS is to maintain consistency with something, and if that something isn't the business domain, then what good does it do?
I don't know where over-modeling fits in the argument. Business logic in an isolated part of an application is likely to age better than something that is intertwined with a database or other external dependencies.
Databases aren't simply persistence layers, they also encompass querying which implicitly couples your application to them. The simplest query model is the key value store, which itself is a form of coupling, but it's quite limited in the operations it can support with high performance.
GraphQL is similarly not a transport layer. The transport layer for GraphQL is HTTP. GraphQL is a query language. To use it with a particular database you need to transpile GraphQL to the query language supported by your database. Usually this is done in an unprincipled manner with ad-hoc code. In other cases it's done more globally and formally, as I assume Hasura is trying to do.
Heh i kind of agree here. Reasonable docs , easy to bootstrap and completely unaware of the underlying performance probs you are about to create bc it “just works”. Curious to your reasons though ?
Apparently the facebook team (and others in production I'm guessing) addresses some of this by only having a whitelisted set of queries in production. So you get the GraphQL flexibility during development, but a effectively a static set of APIs in production.
but GraphQL isn't a storage engine. or are you saying that in a few years we'll realize we've been using to solve a whole lot of things that really didnt need solving?
This is a good trend. Will we see more work aimed at separating the data model and human interface (to make programming with attributed graphs safe and convenient) from back end issues (how to store data and process queries efficiently, where traditional databases are already very advanced.)
I see that one of the ways you want to monetize this is by offering support. Providing support is a good approach to monetize an open source project but it’s not very scalable. Have you thought of any other ways you can monetize this?
If others in the HN community can pitch in with any ideas they have on how to monetize an open source project that would be great as well.
We do not batch queries. We take a slightly different approach. We convert the GraphQL query AST into a single SQL query (no matter how nested the GraphQL query is).
It's in an early preview right now, and we should have something in a week or two! Just going through some performance and security checks over the next few days.
Do feel free reach out to us via discord if you'd like to take it for a spin.
I have a bit of a dumb question: where does GraphQL fit in a stack? I've seen in used primarily as a means of aggregating a bunch of disparate microservices, but then I see things like this that put it in the role of app server, almost. What advantages does this give over, for example, a Rails API (also on Postgres)? If it is supposed to fill the role of app server, how do you handle things more involved than simple CRUD operations? Like, if I sign up a user, how -- in a GraphQL world -- would I send a welcome email, typically?
We’re experimenting with it on a new product at my company, and this is how we use it. Specifically, we use it as an API gateway in front of a bunch of restful services.
Another benefit is a more robust type system than you get with JSON. GraphQL supports union types, interfaces, etc., allows you to provide more strongly typed contracts between the backend and frontend.
One downside though - while the responses can become smaller, with fewer round trips, the requests get A LOT bigger (than with REST), as you have to specify every field, subfield, etc. This is especially true if you make heavy use of union types - then you have to specify all the fields, sub fields, etc. of all the various concrete members you might get back. Like requests with payloads over 1KB is not uncommon. If you’re polling, and the result of the polling is generally an empty response, you may end up sending significantly MORE data over the wire, not less.
I believe it's intended as an API gateway, a means of creating a single front-facing web API for one or (usually) more back-end services. That way, clients can pick and mix apis and the data they want from it (e.g. streaming posts for mobile, or 20 posts at a time for desktop), without a developer having to create a REST / Rails API endpoint for each possible use case / client.
In practice it is like exposing a very limited interpreter directly to the public internet. Instead of working with resources and limited verbs and hypermedia or SOAP (which is literally just documents) you allow clients to submit what are essentially programs with are then evaluated. In other words its mobile code all over again. [1]
well yeah, there is a reason why graphql gets called 'sql for web services' after all.
but I wasn't trying to draw a parallel between implementations...
while you're obviously right that the implementation and the way you actually interface with GraphQL is very different from REST, just like that differed from SOAP, its nonetheless the same use-case.
They're all communication protocols between different software components.
There could be 2 ways to solve that specific problem of sending a welcome email:
1) Write a GraphQL schema stitching gateway, that can write a custom mutation that delegates to another API (or GraphQL API) to write to the database, or writes to the database directly. This is becoming popular as more backend services expose their functionalities via GraphQL.
2) React asynchronously after the database write is done. Put the database event in a queue, for example, that runs the email send async-ly.
The most prevalent use case for GraphQL right now is to act as a thin API layer over a bunch of microservices (which is what Facebook originally developed it for) -- but that is not the only use case.
GraphQL is actually much less than a replacement for a REST API. Its really just a type system with an execution engine that can map queries against that type system to resolvers (functions). That's it. This means that you can actually use it all over the place:
- Because it provides a strongly typed interface, you could use GraphQL as the basis of an RPC protocol (infact, GraphQL doesn't specify a transport mechanism, since its only job is to map queries to functions, so you could send GraphQL queries over RabbitMQ if you wanted to.. or encode them with protobuf and send them via HTTP/2).
- You could use a GraphQL schema to define the internal object model of an application and use GraphQL internally as a data access layer. You don't even have to expose it outside your codebase.
- You can use the tooling that comes with GraphQL (at least in the Node.js implementation) to parse incoming queries into their abstract syntax trees and to all kinds of fun stuff with them (automagically stitch multiple GraphQL schema's together into a combined API).
- I'm actually working on a proxy layer that can actually sit on top of an existing GraphQL API and apply additional logic to the incoming request and outgoing responses (it would actually be a good fit as a business logic layer for a Hasura based GraphQL api)
I think that in the future we'll see lots of very interesting uses of GraphQL that go beyond is current status as "REST API replacement"
*To answer your question "if I sign up a user, how -- in a GraphQL world -- would I send a welcome email, typically?" -- Define a mutation (update method) in your GraphQL schema to create a new user. Inside the resolver (function that is executed) for that mutation, write code to create a user (API call? Database update?) and send an email (drop a message in a queue to your email sending serivce?). It works just like it would for any other application codebase, you just initiate process with a GraphQL query, instead of, say an HTTP Post to a REST API.
I always thought it was in the name- a web API standard inspired by SQL over a graph data structure. This way, rather than having to predefine API endpoints that are super customized, you define fewer that follow the standard and act as a standard interface. Like if HTTP client = ODBC and GraphQL = SQL.
Broadly similar projects! The emphasis of Hasura is to make it seamless to work with existing databases.
The primary difference is how authorization is handled. In Postgraphile, you map your application roles to Postgres users and define policies using Postgres's RLS. With Hasura, you define rules on roles (similar to Postgres's RLS) but it integrates into your existing auth system using webhooks.
Also, peripherally, we have quite a bit of tooling with an admin UI and a rails-like migration system to make the dev workflows easier :)
> The emphasis of Hasura is to make it seamless to work with existing databases.
Yet, I spent 15 minutes searching for example of using Hasura with an existing schema. Your "Getting Started" page has two examples: Deploy on Heroku and Run with Docker - in both cases, using a fresh database, not an existing one.
Nice work. There are several competitors in the automagic Postgres REST/GraphQL space, and you're nailing documentation and ergonomics here. Your site and the Hansura Console sets your project apart from the rest.
I work with a Django app on Postgres, and I'm not sure how I would migrate that to GraphQL. How things play out in terms of django specific tables? What about relationships between tables? We mostly use the Django app to expose REST APIs, which deal with making complex queries using QuerySets to Postgres. Moving this to GraphQL mean that all the business logic that sits on the REST APIs need to be moved to the frontend?
Well it depends on your app. Technically, you have to rebuild your app to speak GraphQL to the frontend instead of REST. Internally, your GraphQL resolvers (like URL handlers) would then do similar work with using QuerySets as you're doing now.
If you'd like to leverage Hasura, it would be a good fit to potentially replace the "read" portions of your app with GraphQL quite easily. And then eventually you would have to move to writing a GraphQL gateway to handle some of the transactional logic and delegate the other stuff to Hasura via schema-stitching.
We at Sale Stock (fashion e-commerce in Indonesia) built an in-house system similar to this but more automatic and works with CockroachDB. Not open source yet, but might be interesting to you guys: https://speakerdeck.com/salestock/laskar-high-velocity-graph... (skip to around mid-way, first half is intro to GraphQL)
As a newbie to GraphQL who is having some growing pains adopting a UI for a data warehouse that was basically bolted onto a REST API designed for backend queries, can someone help me understand what the pros and cons are for something like this vs hand rolling all of the backend GraphQL stuff yourself? We have been evaluating switching/offering a GraphQL backend for our UI to consume for our product since it seems well suited to our use case but so far the effort required has outweighed the gain we would get from it. Because of this a somewhat turnkey solution like above might be more appealing.
I think it depends on how much business logic you have in your REST API layer. If you can get away with using a turnkey solution like hasura with the right access control rules or by adding schema stitching then it would save a lot of effort.
I think the best thing would be to try a turnkey solution for your appliaction's database and then evaluating the effort saved. Turnkey solutions also might end up partial effort if not all. For example, Hasura is a great fit for incrementally adding read-only GraphQL queries which is where a lot of benefit of GraphQL for the UI lies.
The GraphQL Engine is written in Haskell, the Console in JavaScript and the CLI in Go. The repo contains all the three components. :) (I am one of the maintainers)
Thank you for releasing this. I am impressed with Hasura! No knock on postgraphile, I am trying that out too as well as prisma, but this looks very well done and the boundaries are clear (like postgraphile, views are important to make things work). Your UI is going to make people happy.
I have two questions: 1. can I point the hasura cli at my local install? and 2. Can we have UUID fields? I'd like to use them as primary keys.
2. For UUID just do what you would normally do. We don’t have it on the column drop down but you can create the table via the run_sql window with the right type and default value, if you’re generating the UUID server-side
This is a standalone service that gives you GraphQL on Postgres. It comes with fine-grained access control that can integrate with any auth provider. It can also work with any existing postgres database as is, and allows you to expose select tables/views across your postgres schemas over GraphQL.
Looking forward to your feedback!
reply