I’ve looked quite a bit at GraphQL in 2019 and I still believe it is an essential part of modern architectures. It allows a diverse set of clients to query and modify your backend system and provides exactly the data that is requested. In addition, GraphQL can be used to provide a modern API to legacy backend systems or can even combine these APIs into a single one. Due to the schemas of GraphQL systems, excellent developer support tools such as GraphiQL are available: while writing GraphQL queries will initially be new to a lot of devs, these tools really ease the pain by providing type-ahead support for example.
Hasura is a GraphQL server that connects to PostgreSQL databases and other services that you might want to expose via a single GraphQL API. While I’ve been using their (commercial) cloud service for this blog post, the open source version of Hasura also seems to be easy to get started with. As the GraphQL engine as well as PostgreSQL are available as Docker containers, running a test installation on your local machine or on Kubernetes looks straightforward
Tracking Tables and exposing them via GraphQL
Besides installing Hasura and pointing it at your PostgreSQL database, you will need to track the tables that you want to expose. In my example, I first had to create this table in the Hasura console. I chose to create a simple “visitors” table with some columns suitable for contact tracing in a restaurant as that’s a use case that is quite common these days.

Once tracked tables are available, you can immediately use them for GraphQL queries, via the built-in GraphiQL UI right besides the data tab. At this point I am assume you are a bit familiar with GraphQL, but if not it’s the perfect time to look at my past blog posts about GraphQL like this intro to get a basic understanding.

The built-in GraphQL explorer will help a lot to build queries, mutations or even subscriptions. Just to recap – a GraphQL query is used to request data from the GraphQL server. The GraphQL server executes the query and returns the specific data requested. Mutations are used to alter data in the backend or backend PostgreSQL database in this case. Using mutations, you update rows or delete rows and return the number of affected rows typically. Finally, with subscriptions you keep a live bi-directional connection between the server and the client in order to get updates on data changes. This is excellent to push updates to the connected clients, just think of order statuses or a customer service chat application where this feature would come really handy.
Remote Schemas
Things start to get really interesting when it comes to the remote schema feature of Hasura. GraphQL is an excellent tool to merge diverse backend systems under a single GraphQL endpoint. If you have other GraphQL endpoints already available, you can very easily configure these in Hasura and offer the combined schema via the single GraphQL endpoint.
To try this out, I’ve created a small node.js. based Glitch application to offer a sample GraphQL endpoint via the well-known (and also open source) Apollo GraphQL Server. It’s as simple as it can get, but it’s really running a full GraphQL endpoint.
const { ApolloServer } = require('apollo-server');
const gql = require('graphql-tag');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "world, SAP Customer Experience Labs rocks!",
}
};
const schema = new ApolloServer({ typeDefs, resolvers });
schema.listen({ port: process.env.PORT}).then(({ url }) => {
console.log(`schema ready at ${url}`);
});
Once the GraphQL endpoint has been added to the Hasura remote schemas, the simple query that I implemented over in the remote GraphqL endpoint becomes magically available under the single Hasura GraphQL endpoint. While mixing these queries with queries from the PostgreSQL tracked tables seems not supported, this is still a pretty valuable feature as it allows you to transparently change the underlying implementation. You can also choose to pass on the headers of the original GraphQL request or define new ones to pass on which is probably needed for authentication and authorization.

Events
Using Hasura, you can setup webhooks that are triggered based on insert/update/delete actions on the tracked PostgreSQL tables. This is an extremely powerful feature, especially if you comebine it with serverless webhook endpoints for example. To give this feature a good try, I created an event for “inserts” on my “visitors” table. So whenever a GraphQL mutation that inserts data into the visitor’s table is executed, an external webhook can be notified. This could be useful to tell the service of a restaurant that a new client has just registered for example…

The endpoint URL for this webhook was created with another Glitch node.js / express server and looks quite unspectacular, so I am not describing it here further. It’s just important to understand that the full data on the insert (like all columns data) as well as all metadata such as the operation (here: insert) as well as the user executing the insert is sent on via the payload of the webhook.
Actions
While Hasura events are executed once GraphQL mutations “change the database” – e.g. upon insert, update or delete operations, Actions are executed before it hits the database. Actions can also be used for both queries and mutations and essentially use HTTP handlers to integrate custom business logic, data validation or data enrichment/transformation. For mutations, Hasura actions can also be run asynchronously. This means the request will be responded to immediately with an aciton_id that can then be used by the client to query the status of fulfillment or – even better – be informed on changes using GraphLQ subscriptions.
As Hasura Actions can also simply extend the GraphQL schema and not be related to any PostgreSQL database at all. But in any case, you need to define the extensions to the schema, which means you need to define the custom types for the query or mutation that you offer.
As you can see in my sample action “actionOne” below, I am defining a SampleInput and SampleOutput custom type to be used for the actionOne action. The use case here is to resolve latitude and longitude of a location into the current temperature at this location. This could be easily performed via an external weater API service for example.

As you may guess, the implementation for this HTTP handler is again on Glitch and for the purpose of testing this out as simple as possible. It just returns a static value to see if the HTTP handler was invoked correctly.
// Request Handler
app.post('/actionOne', async (req, res) => {
return res.json({
temp: "20"
})
});
Yet, back in the GraphiQL UI, this custom extension to the GraphQL schema can now be used via the same GraphQL endpoint:

Conclusion
With this quick exploration and blog post, I hope I was able to give you a quick overview about Hasura. I’ve also ticked off the task to look into Hasura for myself, which might come really handy for some future prototypes. Hasura is a GraphQL powered data-access layer for PostgreSQL databases and its also able to integrate really well with external, remote systems that can be accessed via HTTP (Hasura actions, events).
Feel free to get in touch – either comment below of just send me a tweet.