Hasura als Instant GraphQL API über PostgreSQL: wann es passt
AI generated
{ }
type
GraphQL · Hasura · PostgreSQL
Hasura als Instant GraphQL API
über PostgreSQL: wann sich der Ansatz lohnt

Hasura verwandelt eine bestehende PostgreSQL-Datenbank in Sekunden in eine vollständige GraphQL-API, inklusive Filtern, Sortierung, Pagination und Beziehungen, ganz ohne einen einzigen Resolver zu schreiben. Der Ansatz eignet sich hervorragend für bestimmte Szenarien und ist für andere komplett ungeeignet. Dieser Artikel zeigt konkret, wo die Grenze verläuft.

18 Min. Lesezeit Hasura · PostgreSQL · Row-Level-Security · Actions Docker · Remote Schemas · Event-Triggers

1. Was ist Hasura und wie generiert es GraphQL aus PostgreSQL

Hasura ist eine GraphQL-Engine, die sich mit einer bestehenden PostgreSQL-Datenbank verbindet, das Datenbankschema per Introspection ausliest und daraus automatisch ein vollständiges GraphQL-Schema mit Queries, Mutations und Subscriptions für jede Tabelle generiert. Anders als bei graphql-php, Lighthouse oder NestJS GraphQL schreibt bei Hasura niemand Resolver-Code, das Query-Verhalten wird direkt in performantes SQL übersetzt, mit optimierten Joins für verschachtelte Beziehungsabfragen.

Der zentrale Denkfehler beim ersten Kontakt mit Hasura ist, es als reines Entwicklungswerkzeug für Prototypen zu betrachten. Tatsächlich betreiben zahlreiche Unternehmen Hasura produktiv als primäre Daten-API, weil die generierten Queries in der Regel effizienter sind als naiv geschriebene Resolver-Ketten, und weil die eingebaute Permission-Engine echte Row-Level-Security auf Datenbankebene durchsetzt, nicht nur auf Anwendungsebene. Für Domänen, deren GraphQL-Struktur eng am relationalen Schema hängt, ist Hasura also durchaus produktionstauglich, nicht nur ein Entwicklungs-Hilfsmittel.

2. Setup: Docker, Metadata und erste Tabelle

Der schnellste Einstieg in Hasura läuft über Docker Compose, das den Hasura-GraphQL-Engine-Container zusammen mit einer PostgreSQL-Instanz startet. Nach dem Start verbindet sich Hasura über eine Connection-String-Konfiguration mit der Datenbank und zeigt im integrierten Console-Interface alle vorhandenen Tabellen an, jede einzelne mit einem Klick als GraphQL-Typ aktivierbar. Diese Konfiguration, welche Tabellen, Views und Funktionen exponiert werden, landet in versionierbaren YAML-Metadata-Dateien, die sich wie normaler Code in Git verwalten lassen.

Wichtig für produktive Setups: Die Metadata-Dateien sollten nie ausschließlich über die Web-Console verändert werden, sondern über hasura metadata export und hasura metadata apply als Teil eines CI/CD-Workflows, damit Änderungen an Permissions, Relationships und Actions nachvollziehbar reviewt werden können, statt sich unversioniert in der laufenden Instanz anzusammeln.


# docker-compose.yaml — Hasura GraphQL Engine with PostgreSQL
version: "3.6"
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: postgrespassword
    volumes:
      - db_data:/var/lib/postgresql/data

  graphql-engine:
    image: hasura/graphql-engine:v2.40.0
    ports:
      - "8080:8080"
    environment:
      HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
      HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
      HASURA_GRAPHQL_ADMIN_SECRET: changeme
    depends_on:
      - postgres

volumes:
  db_data:

-- products table — Hasura tracks this and exposes it as a GraphQL type instantly
CREATE TABLE products (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    sku TEXT UNIQUE NOT NULL,
    name TEXT NOT NULL,
    price NUMERIC(10, 2) NOT NULL,
    category_id UUID REFERENCES categories(id),
    created_at TIMESTAMPTZ DEFAULT now()
);

3. Permissions: Row-Level-Security im Berechtigungssystem

Das Hasura-Berechtigungssystem definiert pro Tabelle und Rolle separate Regeln für Select, Insert, Update und Delete, jede als deklarativer Filterausdruck ähnlich einer SQL-WHERE-Klausel. Eine Regel wie {"customer_id": {"_eq": "X-Hasura-User-Id"}} sorgt dafür, dass ein authentifizierter Kunde ausschließlich seine eigenen Bestellungen sehen kann, wobei X-Hasura-User-Id ein Session-Variable ist, die von der Authentifizierungsschicht, meist über JWT-Claims, gesetzt wird.

Der entscheidende Vorteil dieses Modells gegenüber Autorisierungslogik in Resolver-Code: Die Row-Level-Permission wird direkt in die generierte SQL-Query als zusätzliche WHERE-Bedingung eingebettet, es gibt also keinen Weg, sie versehentlich zu umgehen, weil sie nicht als separater, potenziell vergessener Prüfschritt existiert, sondern strukturell Teil jeder einzelnen Abfrage ist. Für Spalten-Ebene bietet Hasura zusätzlich Column-Permissions, mit denen sich etwa ein internal_notes-Feld nur für die Rolle admin sichtbar machen lässt.


// Hasura metadata — row-level permission for role "customer" on table "orders"
{
  "table": { "schema": "public", "name": "orders" },
  "select_permissions": [
    {
      "role": "customer",
      "permission": {
        "columns": ["id", "status", "total", "created_at"],
        "filter": {
          "customer_id": { "_eq": "X-Hasura-User-Id" }
        },
        "limit": 100
      }
    }
  ]
}

4. Relationships: Object- und Array-Beziehungen modellieren

Beziehungen zwischen Tabellen werden in Hasura als Object-Relationship für Many-to-One und Array-Relationship für One-to-Many oder Many-to-Many konfiguriert, jeweils auf Basis der bestehenden Foreign-Key-Constraints in PostgreSQL. Existiert bereits ein Foreign Key, erkennt Hasura die Beziehung automatisch und schlägt sie zur Aktivierung vor, ansonsten lässt sich die Beziehung auch manuell über beliebige Spaltenkombinationen definieren, etwa für Legacy-Schemas ohne saubere Foreign-Key-Constraints.

Verschachtelte GraphQL-Queries über diese Relationships übersetzt Hasura automatisch in effiziente SQL-Joins, ganz ohne das klassische N+1-Problem, das bei handgeschriebenen Resolvern ohne DataLoader typisch ist. Eine Query nach 50 Produkten mit jeweils zugehöriger Kategorie erzeugt bei Hasura eine einzige SQL-Abfrage mit JOIN, nicht 51 separate Abfragen, ein struktureller Performance-Vorteil gegenüber naiv implementierten Resolver-basierten APIs.


# Nested query resolved by Hasura as a single SQL JOIN, no manual DataLoader needed
query ProductsWithCategory {
  products(where: { price: { _gt: 20 } }, order_by: { created_at: desc }) {
    id
    sku
    name
    price
    category {
      id
      name
    }
  }
}

5. Custom-Logik: Actions und Event-Triggers

Für Geschäftslogik, die sich nicht als reine Datenbankabfrage ausdrücken lässt, etwa eine Zahlungsabwicklung über einen externen Payment-Provider, bietet Hasura Actions: benutzerdefinierte GraphQL-Mutations, die im generierten Schema erscheinen, aber intern einen HTTP-Request an einen selbst geschriebenen Webhook-Endpunkt auslösen. Der Actions-Mechanismus erlaubt so, beliebigen eigenen Code, etwa in Node.js oder Go, nahtlos in das GraphQL-Schema einzubinden, ohne den Auto-Generierungsansatz für den Rest der API aufzugeben.

Event-Triggers gehen den umgekehrten Weg: Statt auf einen GraphQL-Request zu reagieren, feuern sie automatisch, sobald sich Daten in einer überwachten Tabelle ändern, etwa nach jedem INSERT in die orders-Tabelle. Der Trigger sendet einen HTTP-Request an einen konfigurierten Endpunkt, ideal für Aufgaben wie das Versenden von Bestätigungs-E-Mails oder das Anstoßen asynchroner Hintergrundverarbeitung, ohne dass die Datenbank selbst Trigger-Logik in PL/pgSQL enthalten müsste.

6. Remote Schemas und Remote Joins

Für Fälle, in denen eine bereits existierende GraphQL-API, etwa ein separater Microservice, mit den Hasura-generierten Daten kombiniert werden soll, bietet Hasura Remote Schemas: Ein fremdes GraphQL-Schema wird als zusätzliche Datenquelle registriert und erscheint im vereinten Hasura-Schema neben den datenbankgenerierten Typen, als würde alles aus einer einzigen API kommen. Das eignet sich hervorragend für die schrittweise Migration bestehender Systeme in Richtung Hasura, ohne alles auf einmal umbauen zu müssen.

Remote Joins gehen noch einen Schritt weiter und erlauben, Felder aus dem Remote Schema direkt mit lokalen Datenbanktypen zu verknüpfen, sodass ein Produkt aus der Datenbank ein Feld inventoryStatus aus einem separaten Inventory-Microservice referenzieren kann, als wäre es eine normale Datenbankspalte. Diese Fähigkeit macht Hasura zu einer echten API-Gateway-Alternative für Teams, die verschiedene Datenquellen unter einem einzigen GraphQL-Endpunkt vereinen möchten.

7. Performance: Query-Caching und Connection-Pooling

Hasura bringt eingebautes Query-Response-Caching mit, das häufig wiederholte Queries anhand ihrer Struktur und Variablen cacht, konfigurierbar über eine @cached-Direktive direkt in der GraphQL-Query. Für Lesezugriffe auf selten wechselnde Daten, etwa eine Produktkategorie-Liste, reduziert das die Datenbanklast erheblich, ohne dass ein separates Caching-Layer wie Redis manuell integriert werden müsste.

Für Connection-Pooling zur Datenbank nutzt Hasura standardmäßig einen internen Pool, dessen Größe sich über HASURA_GRAPHQL_PG_CONNECTIONS konfigurieren lässt. Bei hoher Parallelität empfiehlt sich zusätzlich ein vorgeschalteter externer Pooler wie PgBouncer, weil PostgreSQL selbst mit einer begrenzten Anzahl gleichzeitiger Verbindungen arbeitet und ein unkontrolliert wachsender Hasura-Pool bei Lastspitzen schnell an diese Grenze stößt.

8. Wann Hasura NICHT passt

So mächtig der Auto-Generierungsansatz von Hasura ist, für bestimmte Szenarien ist er strukturell ungeeignet. Domänen mit komplexer, mehrstufiger Geschäftslogik, etwa ein Bestellprozess mit Rabattregeln, Lagerbestandsprüfung und mehreren Validierungsschritten, lassen sich nicht sinnvoll als reine Datenbankoperation ausdrücken. Zwar lässt sich das über Actions lösen, aber dann verlagert sich der Großteil der eigentlichen Logik ohnehin wieder in selbst geschriebenen Code, und der Auto-Generierungsvorteil von Hasura schrumpft entsprechend.

Ebenfalls ungeeignet ist Hasura für GraphQL-Schemas, die bewusst stark von der relationalen Datenbankstruktur abweichen sollen, etwa wenn das API-Design aus fachlichen Gründen anders aussehen soll als das zugrunde liegende Tabellenschema. Und für Teams, die volle Kontrolle über jeden Aspekt der Query-Ausführung brauchen, etwa für sehr spezifisches Custom-Caching pro Feld, ist der deklarative Hasura-Ansatz einschränkender als eine handgeschriebene graphql-php- oder NestJS-Lösung mit vollständig freien Resolvern.

9. Hasura vs. handgeschriebenes GraphQL

Die Entscheidung zwischen Hasura und einer manuell geschriebenen GraphQL-API hängt stark davon ab, wie eng die Domäne an die relationale Datenbankstruktur gekoppelt ist.

Kriterium Hasura Handgeschriebenes GraphQL
Zeit bis zur ersten funktionierenden API Minuten Tage bis Wochen
N+1-Vermeidung Automatisch per SQL-Join Manuell per DataLoader
Komplexe Geschäftslogik Nur über Actions, mit eigenem Code Nativ im Resolver
Schema-Struktur vs. DB-Struktur Eng gekoppelt Frei wählbar
Row-Level-Security Eingebaut, deklarativ Selbst zu implementieren

Für datengetriebene Anwendungen mit überwiegend CRUD-artigen Zugriffsmustern und klaren Row-Level-Berechtigungen, etwa interne Admin-Tools, Dashboards oder Backend-for-Frontend-Schichten über einer bestehenden Datenbank, ist Hasura oft die schnellere und wartungsärmere Wahl. Für Domänen mit tiefer, verzweigter Geschäftslogik oder einem API-Design, das bewusst von der Datenbankstruktur abweicht, bleibt eine handgeschriebene Lösung mit graphql-php, Lighthouse oder NestJS die passendere Grundlage.

Mironsoft

GraphQL-, PostgreSQL- und API-Architektur für datenintensive Systeme

Prüfen, ob Hasura zu eurer Datenbank passt?

Wir bewerten eure PostgreSQL-Struktur, richten Hasura mit sauberen Row-Level-Permissions und Relationships ein und zeigen ehrlich, wo Actions oder eine handgeschriebene GraphQL-Lösung die bessere Wahl sind.

Hasura-Setup

Metadata-basierte Konfiguration, versioniert und CI/CD-tauglich einrichten

Permissions & Security

Row- und Column-Level-Permissions passend zu eurem Rollenmodell modellieren

Architektur-Review

Ehrliche Einschätzung, wann Hasura passt und wann nicht

10. Zusammenfassung

Hasura generiert aus einer PostgreSQL-Datenbank eine vollständige, performante GraphQL-API mit Row-Level-Permissions, automatisch erkannten Relationships und eingebauter N+1-Vermeidung durch SQL-Joins, ganz ohne einen einzigen Resolver zu schreiben. Für datengetriebene Anwendungen mit überwiegend CRUD-artigen Zugriffsmustern reduziert das die Entwicklungszeit von Wochen auf Minuten und liefert dabei eine deklarative, in Metadata versionierbare Konfiguration.

Der Auto-Generierungsansatz stößt jedoch an klare Grenzen: komplexe, mehrstufige Geschäftslogik, die sich nicht als Datenbankoperation ausdrücken lässt, und Schemas, die bewusst von der relationalen Struktur abweichen sollen, passen strukturell schlecht zu Hasura. Actions und Remote Schemas mildern diese Einschränkung ab, ersetzen aber nicht vollständig die Flexibilität einer handgeschriebenen graphql-php-, Lighthouse- oder NestJS-Lösung. Die richtige Wahl hängt letztlich davon ab, wie eng die eigene Domäne an das relationale Datenbankschema gekoppelt ist.

Hasura als Instant GraphQL API — Das Wichtigste auf einen Blick

Auto-Generierung

Vollständiges GraphQL-Schema direkt aus PostgreSQL-Introspection, versioniert in Metadata-YAML-Dateien.

Permissions

Row- und Column-Level-Security als Teil jeder generierten SQL-Query, nicht umgehbar wie Resolver-basierte Checks.

Actions & Remote Schemas

Eigener Code und externe APIs lassen sich nahtlos ins generierte Schema integrieren.

Grenzen

Komplexe Geschäftslogik und stark abweichende Schema-Designs passen strukturell schlecht zum Ansatz.

11. FAQ: Hasura als Instant GraphQL API

1Was ist Hasura?
Eine GraphQL-Engine, die aus PostgreSQL per Introspection automatisch ein vollständiges GraphQL-Schema generiert, ohne Resolver-Code.
2Nur für Prototypen oder auch Produktion?
Auch für Produktion, viele Unternehmen nutzen Hasura als primäre Daten-API mit echter Row-Level-Security.
3Wie funktionieren Permissions?
Deklarative Filterausdrücke pro Tabelle und Rolle, direkt in die generierte SQL-Query eingebettet und damit nicht umgehbar.
4Vermeidet Hasura N+1?
Ja, automatisch per SQL-Join für verschachtelte Relationship-Queries, ohne manuelles DataLoader-Pattern.
5Wie eigene Logik integrieren?
Über Actions, die als GraphQL-Mutations erscheinen, intern aber einen eigenen Webhook-Endpunkt per HTTP aufrufen.
6Was sind Event-Triggers?
Automatische HTTP-Requests bei Datenänderungen in überwachten Tabellen, etwa für E-Mail-Versand oder Hintergrundverarbeitung.
7Kombinierbar mit bestehender GraphQL-API?
Ja, über Remote Schemas und Remote Joins, die fremde APIs nahtlos ins vereinte Hasura-Schema integrieren.
8Wann passt Hasura nicht?
Bei komplexer Geschäftslogik jenseits reiner Datenbankoperationen und bei Schemas, die bewusst von der DB-Struktur abweichen sollen.
9Wie Metadata verwalten?
Über hasura metadata export/apply als Teil von CI/CD, nicht nur über die Web-Console, für versionierte, reviewbare Änderungen.
10Braucht Hasura zwingend PostgreSQL?
PostgreSQL ist am besten unterstützt, weitere Datenbanken wie MySQL oder BigQuery werden mit teils eingeschränktem Funktionsumfang unterstützt.