Show HN: Hasura – Fast, instant GraphQL APIs on Postgres
github.com
github.com
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?
[0]: https://github.com/facebook/graphql/issues/91#issuecomment-2...
[1]: https://www.postgresql.org/docs/9.1/static/queries-with.html
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])
[1] https://github.com/hasura/skor [2] https://github.com/hasura/pgdeltastream
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! :)
We have an example of schema stitching in this repo https://github.com/hasura/graphql-schema-stitching-demo
It stitches a weather API schema and a person schema. Hope it gives an idea.
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.
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.
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!
As you work at Hasura I assume you are aware that Prisma does work with existing postgres databases. You can look up the documentation for introspecting an existing database at https://www.prisma.io/docs/reference/service-configuration/d...
Full disclosure - I am the co-founder of Prisma.
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.
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?
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 :-)
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.
We're also planning to release a lot of cool GraphQL OSS stuff for the haskell community because of our work over the last year.
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.
[1] https://docs.hasura.io/1.0/graphql/manual/auth/index.html
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.
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.
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.
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!
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.
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.
How much of the code base (and complexity) is doing that vs the auto-schema mapping and whatnot?
I would just "read the source, Luke" but haskell isn't one of those languages I can idly read.
* Responses either contain more data than you need, or not enough data (e.g. you need data for related entities as well).
* With REST, if you need data for related entities then you need to perform additional REST calls, resulting in more network roundtrips.
With GraphQL you can specify exactly what you want, and the server responds with just that, in a single call.
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.
Just like there are frameworks for these protocols, this is one that automatically creates a service for a postgres database.
postgrest[0] would probably be it's REST equivalent.
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]
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.
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.
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.
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.
Unless – of course – you simply want something working quickly that does not need to be maintained or kept alive for a long time.
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 :)
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.
EDIT: Docs updated, we'll keep improving it too :)
Homepage has the GitLab example, but not actual "Getting Started" page.
We're on https://hasura.io too.
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.
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.
It would be awesome if it could be made compatible with Postgraphile (https://www.graphile.org/postgraphile/introduction/)
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.
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
Better support for ENUMS and MANY TO MANY relationships would be very needed though.
We're adding docs for enums as we speak. What did you find lacking around the many-to-many?
Example: I have 3 tables pages, page_blocks, and blocks.
- Inserting blocks into a page is tough.
- To query it's not very intuitive I would like to do.
pages {
blocks {
id
}
}& not
pages {
page_blocks {
blocks {
id
}
}
}Do feel free reach out to us via discord if you'd like to take it for a spin.
I’ve never used it so my opinion isn’t fully baked, but every time I look at the docs I’m just like wtf.