How to add a GraphQL API to dev.to in a few minutes
Tags: graphql, hasura, meta
Published: 2019-01-12 18:14:08

## Why you're reading this

* dev.to has a REST API that is probably becoming public in the near future
* GraphQL is a solid and proven technology now and is one of those that [many people here want to get comfortable with in 2019](https://dev.to/emmawedekind/what-technology-do-you-want-to-learn-in-2019-dfh)
* PostgreSQL (which dev.to uses) is my favorite relational database

I decided to try [Hasura](https://hasura.io/) which promises to let people build a GraphQL API that speaks directly to the PostgreSQL database.

I didn't expect to be done with my demo 15 minutes later writing only the GraphQL queries themselves and one SQL statement. No other code at all.

Let me backtrack a bit and explain what Hasura is.

## Hasura

The tool is a GraphQL engine/server written in Haskell and JavaScript. It sits between a client application (API consumer for example) and the database (PostgreSQL).

The client sends the GraphQL query, the server gets it, parses it, validates it, transforms it to a highly optimized SQL query, fetches the data in JSON format (PostgreSQL allows you to export data in JSON without going back to the web app, one of its best recent features if you ask me) and sends it back to the client.

If you want to read more about the architecture you can read Hasura's article: [Architecture of a high performance GraphQL to SQL engine](https://blog.hasura.io/architecture-of-a-high-performance-graphql-to-sql-server-58d9944b8a87).

So, after reading only that article out of curiosity, I decided to give it a go trying to read as little documentation as possible.

It went well.

## Setting up the server

The setup is quite straightforward. I installed [Docker for Mac](https://docs.docker.com/docker-for-mac/install/), [downloaded a script](https://docs.hasura.io/1.0/graphql/manual/deployment/docker/index.html), ran its contents and waited:

```shell
docker run -p 8080:8080 -e HASURA_GRAPHQL_DATABASE_URL=postgres://username:password@host:port/db -e HASURA_GRAPHQL_ENABLE_CONSOLE=true hasura/graphql-engine:v1.0.0-alpha34
```

After that, I opened the console with a browser and this appeared:

![](https://thepracticaldev.s3.amazonaws.com/i/166hfheajci0syvof93c.png)

## Preparing the schema

Clicking on `Data` reveals the list of tables contained in the database chosen. I instructed Hasura to expose the `articles`, `comments` and `users` table, clicked around a bit in the UI to [create relationships between them](https://docs.hasura.io/1.0/graphql/manual/schema/relationships/index.html) and the result was the following:

![](https://thepracticaldev.s3.amazonaws.com/i/xj0x1aw7z36lllg6pj1j.png)

The only thing I had to setup manually is `articles_comments` which doesn't exist in the default dev.to database. 

Hasura [doesn't support](https://github.com/hasura/graphql-engine/issues/1167) [polymorphic associations](https://guides.rubyonrails.org/association_basics.html#polymorphic-associations) as they are created by Ruby on Rails. The solution, found searching the [issue tracker](https://github.com/hasura/graphql-engine/issues/1167), was to create a simple view:

```sql
create view articles_comments as select * from comments where commentable_type  = 'Article';
```

### Querying the data

With the schema and the relationship setup I went on two write a few GraphQL queries with and without nested data to see if everything worked.

**the last 10 users with their last 3 comments**

![](https://thepracticaldev.s3.amazonaws.com/i/0nxegkrnydb451qvh45j.png)

**the most popular article with the most popular comment and the name of its author**

![](https://thepracticaldev.s3.amazonaws.com/i/tm275qvs9eirarq0sq3m.png)

This last query is one of those reasons why GraphQL can be advantageous over REST. REST(ish) APIs tend to be kind of a drag when you need to ask for nested or related data. Think about it, we're asking the web server to retrieve the post with the most reactions, then fetch the comment with the most likes and its author. 

In a classic REST(ish) API you would invoke the HTTP web server three times:

* give me the article sorted by popularity
* give me the comment sorted by popularity, here I give you the id of the article
* give me the user, here I give you the comment id

You might get to one HTTP call in some REST APIs but it's a possibility, not the default. GraphQL in this case lowers the barrier: 

* any GraphQL client can talk to your server without speaking your own version of REST
* the roundtrip is only one
* the API is self documenting, which is a huge advantage during the exploration phase

Clicking on the "Analyze" button in the Hasura interface yields the SQL and the execution plan:

![](https://thepracticaldev.s3.amazonaws.com/i/jeranf4zxm5ol0qt28dv.png)

I stopped at this point and wrote this article. Hasura though supports [lots of other features](https://hasura.io/all-features):

* mutations
* subscriptions (basically realtime notifications of data changes in the DB, which you can hook up to a UI)
* auth and row level access control (you can decide what to expose and what not to)
* schema stitching (external GraphQL APIs that need to be exposed through yours transparently)
* webhooks on events
* migrations

Hasura also deploys on Heroku, Digital Ocean and Kubernetes.

I only tried it a few minutes so I can't say anything else but it's surely an interesting tool for people who want to build a GraphQL API on top of an existing database.