はじめに
GraphQL APIを自前で作ろうとすると、スキーマ定義、リゾルバの実装、N+1問題の対策、認可ロジックの組み込みと、やることが一気に増えます。データベースにテーブルを1つ追加するたびに、対応するクエリとミューテーションを手で書き足していく作業にうんざりした人も多いのではないでしょうか。
Hasura GraphQL Engineは、この「スキーマとリゾルバを手書きする」工程をまるごと省略してくれるオープンソースのGraphQLサーバーです。PostgreSQLなどのデータベースに接続するだけで、テーブル構造からGraphQLスキーマを自動生成し、CRUD操作に対応したクエリ・ミューテーション・サブスクリプションをその場で使えるようにしてくれます。
この記事では、Hasura GraphQL Engineの特徴からインストール方法、実際にどうAPIを叩くのか、権限管理やカスタムロジックの組み込み方まで、実践的なユースケースを交えて解説していきます。
Hasura GraphQL Engineとは
Hasura GraphQL Engineは、PostgreSQL・MySQL・MS SQL Server・ClickHouse・MongoDBといったデータベースの前段に立ち、データへのアクセスを単一のGraphQL/REST APIとして公開するオープンソースのサーバーです。Haskellで実装されており、Docker イメージとして配布されています。
現在は「Hasura V2」(Apache License 2.0でライセンスされた成熟版)と、新しいコネクタベースのアーキテクチャを採用した「Hasura V3 / Hasura DDN」が並行して開発・提供されています。この記事では、多くの現場で使われている定番の使い方を中心に紹介します。
主な特徴
- 自動スキーマ生成 - データベースのテーブルやビューを指定するだけで、対応するGraphQLの型・クエリ・ミューテーション・サブスクリプションが自動生成されます
- きめ細かなアクセス制御 - ロールごとに「どのテーブルの、どのカラムを、どんな条件で」操作できるかを行レベル・カラムレベルで設定できます
- リアルタイムサブスクリプション -
subscriptionを使うだけで、データベースの変更をWebSocket経由でリアルタイムに購読できます - Actions / Event Triggers - 既存のREST APIやサーバーレス関数をGraphQLスキーマに組み込んだり、データベースの変更をトリガーにWebhookを呼び出したりできます
- リモートスキーマの統合 - 他のGraphQLサーバーをリモートスキーマとして取り込み、単一のエンドポイントに統合できます
インストール
もっとも手軽なのはDocker Composeを使う方法です。PostgreSQLとHasura GraphQL Engineをセットで起動できます。
curl https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/docker-compose/docker-compose.yaml -o docker-compose.yml
docker compose up -d
起動後は http://localhost:8080/console にアクセスすると、Hasura Consoleというブラウザ管理画面が開きます。ここからテーブルの作成やGraphQL APIの動作確認ができます。
CLIを使ってマイグレーションやメタデータをバージョン管理しながら開発したい場合は、Hasura CLIをインストールします。
curl -L https://github.com/hasura/graphql-engine/raw/stable/cli/get.sh | bash
もっと手早く試したい場合は、Hasura Cloudでマネージドインスタンスを数十秒で立ち上げることも可能です。
基本的な使い方
Hasura Consoleで既存のテーブル(例えば articles テーブル)を「Track」すると、そのテーブルに対応するGraphQLのクエリとミューテーションが即座に利用可能になります。テーブルを作成しただけで、以下のようなクエリがそのまま動きます。
query GetArticles {
articles(limit: 5, order_by: { created_at: desc }) {
id
title
published
}
}
データの追加も、insert_<テーブル名> というミューテーションを呼ぶだけです。
mutation AddArticle {
insert_articles_one(
object: { title: "Hasuraを試してみた", published: true }
) {
id
title
}
}
リゾルバを1行も書いていない点がポイントです。テーブルの列やリレーションを変更すれば、GraphQLスキーマも自動で追従します。
実践的なユースケース
リレーションを使ったネストしたクエリ
テーブル同士に外部キーがある場合、Hasuraのコンソール上でリレーションを設定すると、GraphQLクエリの中でネストしたオブジェクトとして関連データを取得できるようになります。例えば articles テーブルと authors テーブルが author_id で結びついている場合、次のように1回のリクエストで著者情報までまとめて取得できます。
query ArticlesWithAuthor {
articles {
title
author {
name
email
}
comments_aggregate {
aggregate {
count
}
}
}
}
comments_aggregate のように、Hasuraは1対多のリレーションに対して件数や合計値を集計する _aggregate フィールドも自動で用意してくれます。手書きのSQL JOINやN+1問題への対策を意識する必要がありません。
ロールベースのアクセス制御(Permissions)
Hasuraの認可はロール単位で設定します。例えば「ログインユーザーは自分が作成した記事だけ更新できる」というルールは、コンソール上でPermissionsルールとして定義でき、内部的には次のようなメタデータ(YAML)として保存されます。
- table: articles
role: user
permission:
columns: [title, body, published]
filter:
author_id:
_eq: X-Hasura-User-Id
check:
author_id:
_eq: X-Hasura-User-Id
X-Hasura-User-Id は、認証プロバイダー(Auth0やFirebase Authなど)が発行したJWTに含まれるセッション変数です。リクエストヘッダーにJWTを付けてAPIを叩くと、HasuraがロールとユーザーIDを読み取り、filter と check の条件に合致する行だけを対象に読み書きを許可します。SQLのWHERE句を毎回手で書かなくても、行レベルセキュリティが実現できるわけです。
Actionsでカスタムビジネスロジックを追加
決済処理や外部サービス連携のように、単純なCRUDでは表現できないロジックは「Actions」としてGraphQLスキーマに組み込めます。Actionsは、実体としては自分で用意したREST APIエンドポイントをHasuraが呼び出す仕組みです。
type Mutation {
sendWelcomeEmail(userId: uuid!): SendEmailOutput
}
type SendEmailOutput {
success: Boolean!
message: String
}
このように独自のミューテーション定義とハンドラーURLをHasura側に登録しておくと、クライアントからは他のフィールドと同じ感覚で sendWelcomeEmail をGraphQL経由で呼び出せます。裏側でどの言語・フレームワークを使っているかをクライアントが意識する必要はありません。
イベントトリガーでWebhookを呼び出す
「新しい注文が orders テーブルに INSERT されたら、在庫確認用のWebhookを呼ぶ」といった非同期処理は、Event Triggersで設定します。対象テーブルと操作(INSERT/UPDATE/DELETE)、呼び出し先のURLを登録するだけで、データベースの変更を起点とした非同期処理が組めます。
- table: orders
event_triggers:
- name: notify_inventory
definition:
insert:
columns: "*"
webhook: https://example.com/webhooks/inventory-check
retry_conf:
num_retries: 3
interval_sec: 10
retry_conf でリトライ回数と間隔を設定できるため、Webhook側が一時的に落ちていても再送によって処理漏れを防げます。バックエンドのメッセージキューを別途構築しなくても、データベースの変更をトリガーにした疎結合な処理連携が実現できます。
まとめ
Hasura GraphQL Engineは、データベースのテーブル構造からGraphQL APIを自動生成し、リレーション、権限管理、リアルタイム購読、カスタムロジックの統合までを一つのエンジンでまかなえるツールです。CRUD APIを都度手書きする代わりに、Permissions・Actions・Event Triggersといった仕組みでビジネスロジックを組み立てていくスタイルは、バックエンド開発のスピードを大きく引き上げてくれます。
まずはDocker Composeでローカルに立ち上げ、手元のテーブルをTrackしてGraphQL APIが即座にできあがる感覚を体験してみるのがおすすめです。そこから権限設定やActionsを組み込んでいけば、本番運用に耐えるAPIの姿が見えてくるはずです。