API Query Language

GraphQL

GraphQL ermöglicht es Clients, exakt die Daten abzufragen, die sie benötigen – und das in einer einzigen Anfrage. Ein typisiertes Schema beschreibt die API, während Resolver die dahinterliegenden Daten abrufen.

intermediate14 min readUpdated 15. Sept. 2026
query.graphql
graphql
// query.graphql
query UserWithPosts($id: ID!) {
  user(id: $id) {
    name
    posts(first: 3) {
      title
    }
  }
}
Erstellt von
Facebook, 2012
Veröffentlicht
2015, Open Source
Schema
Ein typisierter Vertrag
Operationen
Query, Mutation, Subscription
Transport
Meist HTTP, ein einziger Endpoint
Server
Resolver hinter dem Schema

Warum es wichtig ist

Warum Teams auf GraphQL setzen

Nur das abfragen, was man braucht

Clients wählen exakt die Felder aus, die sie verwenden. So gibt es weder Over-fetching noch Under-fetching von Daten.

Eine Anfrage, viele Ressourcen

Eine einzige Query kann Beziehungen durchlaufen, für die ansonsten mehrere REST-Roundtrips erforderlich wären.

Ein typisierter Vertrag

Das Schema ist selbstdokumentierend und ermöglicht Autovervollständigung, Validierung und Codegenerierung.

Das Gesamtbild

Die drei Grundideen von GraphQL

Ein typisiertes Schema beschreibt die Daten, eine Query wählt exakt aus, was benötigt wird, und Resolver liefern die Werte für jedes Feld.

Das Schema

Vertrag

Typen, Felder und Operationen, die exakt beschreiben, was die API zurückgeben kann.

Die Query

Auswahl

Ein Client-Dokument, das Felder auswählt und Argumente sowie Variablen übergibt.

Die Resolver

Auflösung

Funktionen, die die Daten für jedes Feld abrufen, oft aus Datenbanken oder anderen Services.

GraphQL auf einen Blick

Der Kern von GraphQL

Typen und Schema

Objekttypen, Scalars, Enums, Interfaces und Unions.

Queries

Daten lesen, indem Felder aus dem Root-Query-Typ ausgewählt werden.

Mutations

Daten schreiben, mit explizitem Input und einer definierten Rückgabeform.

Subscriptions

Echtzeit-Updates über eine persistente Verbindung streamen.

Variablen und Fragments

Feld-Auswahlen wiederverwenden und typisierte Argumente übergeben.

Clients

Apollo, urql und Relay übernehmen das Caching und die Anfragen.

Eine kurze Geschichte

Von einer internen Facebook-API zum Industriestandard

  1. 2012

    Entwicklung bei Facebook

    Facebook entwickelt GraphQL, um seine mobilen Apps mit effizientem Datenabruf zu unterstützen.

    12
  2. 2015

    Open Source

    Die Spezifikation und die Referenzimplementierung werden öffentlich veröffentlicht.

    15
  3. 2018

    Gründung der Foundation

    Die GraphQL Foundation wird ins Leben gerufen, um die Spezifikation zu verwalten.

    18
  4. 2020

    Mainstream-Adoption

    Apollo, urql und Relay reifen aus, und GraphQL wird in Produkt-APIs zum Standard.

    20
  5. Heute

    Ein Standard-Tool

    Weit verbreitet für öffentliche APIs, interne Services und federated graphs.

    Heute

Der vollständige Leitfaden

GraphQL: Alles was Sie wissen müssen

Was ist GraphQL?

GraphQL ist eine Abfragesprache und Runtime für APIs. Anstatt viele feste Endpunkte bereitzustellen, exponiert ein GraphQL-Server ein einziges, typisiertes Schema. Clients senden Abfragen, mit denen sie exakt die Felder auswählen, die sie benötigen. Der Server löst jedes Feld auf und gibt eine Antwort zurück, die präzise der Struktur der Anfrage entspricht.

Facebook hat GraphQL im Jahr 2012 entwickelt, um ein Problem bei mobilen Anwendungen zu lösen: REST-Endpunkte lieferten entweder zu viele oder zu wenige Daten, und das Abrufen aller für einen Bildschirm benötigten zusammenhängenden Informationen erforderte viele Round-Trips. GraphQL löste beides, indem es dem Client ermöglichte, seine Datenanforderungen in einem einzigen Dokument zu beschreiben.

Das Schema

Das Schema ist der Vertrag. Es definiert die Typen und die verfügbaren Operationen.

# schema.graphql
type User {
  id: ID!
  name: String!
  email: String
  posts(first: Int = 10): [Post!]!
}

type Post {
  id: ID!
  title: String!
  body: String!
  author: User!
}

type Query {
  user(id: ID!): User
  posts(limit: Int): [Post!]!
}

type Mutation {
  createPost(input: CreatePostInput!): Post!
}

Das ! markiert ein Feld als non-null. Typen setzen sich zu einem Graphen zusammen, weshalb eine einzige Query von einem User zu dessen Posts und zurück zu den Autoren navigieren kann. Das Schema ist introspektierbar, sodass Tooling automatisch Dokumentationen, Typen und Autocompletion generieren kann.

Queries

Eine Query wählt Felder aus dem Root-Query-Typ aus, wobei Argumente und Variablen verwendet werden können.

# posts.graphql
query RecentPosts($limit: Int!) {
  posts(limit: $limit) {
    id
    title
    author {
      name
    }
  }
}

Die Antwort spiegelt die Auswahl exakt wider: keine zusätzlichen Felder, keine fehlenden. Variablen machen Queries wiederverwendbar und ermöglichen es dem Server, die Argumenttypen zu validieren. Fragments extrahieren wiederkehrende Auswahlen zur mehrfachen Verwendung.

# fragment.graphql
fragment PostCard on Post {
  id
  title
  author { name }
}

query Feed {
  posts { ...PostCard }
}

Mutationen und Subscriptions

Eine Mutation ändert Daten und gibt eine definierte Struktur zurück – oft einschließlich des aktualisierten Objekts, damit der Client seinen Cache aktualisieren kann.

# create.graphql
mutation CreatePost($input: CreatePostInput!) {
  createPost(input: $input) {
    id
    title
  }
}

Eine Subscription streamt Echtzeit-Updates über eine persistente Verbindung, wie zum Beispiel neue Nachrichten oder Live-Benachrichtigungen. Verwende sie, wenn der Server Daten aktiv an den Client pushen muss; für gelegentliche Aktualisierungen sind Polling oder ein Refetch einfacher.

Resolver

Resolver sind die Schnittstelle zwischen Ihrem Schema und Ihren Daten. Jedes Feld besitzt einen Resolver, der dessen Wert zurückgibt.

// resolvers.js
const resolvers = {
  Query: {
    user: (_parent, { id }, { db }) => db.users.findById(id),
    posts: (_parent, { limit = 10 }, { db }) => db.posts.findMany({ limit }),
  },
  User: {
    posts: (user, { first }, { db }) =>
      db.posts.findMany({ where: { authorId: user.id }, limit: first }),
  },
  Mutation: {
    createPost: (_parent, { input }, { db }) => db.posts.create(input),
  },
};

Das Context-Objekt enthält gemeinsam genutzte Ressourcen wie die Datenbank und den authentifizierten Benutzer. Resolver sollten klein gehalten werden; Autorisierungsprüfungen gehören hierher oder in die Service-Layer, die sie aufrufen – niemals auf den Client.

Das N+1-Problem

Die häufigste Performance-Falle in GraphQL sind N+1-Queries. Wenn eine Query zehn Posts zurückgibt und der Resolver für den Autor jedes einzelnen Posts die Datenbank abfragt, werden insgesamt elf Queries ausgeführt.

DataLoader löst dieses Problem durch das Batching und Caching von Aufrufen innerhalb eines einzigen Requests.

// loaders.js
import DataLoader from "dataloader";

function createUserLoader(db) {
  return new DataLoader(async (ids) => {
    const users = await db.users.findByIds(ids);
    return ids.map((id) => users.find((u) => u.id === id));
  });
}

Der Author-Resolver ruft dann loaders.user.load(post.authorId) auf, und DataLoader sammelt alle Loads innerhalb eines Ticks in einer einzigen Query. Dies ist die wichtigste Optimierung für einen GraphQL-Server.

Clients und Caching

Client-Bibliotheken wie Apollo Client und urql bieten Caching, Normalisierung, Loading- und Error-States sowie eine Integration in UI-Frameworks. Ein normalisierter Cache speichert Entitäten nach Typ und ID, sodass eine Mutation, die einen aktualisierten Post zurückgibt, automatisch jede Query aktualisiert, die darauf referenziert.

Da GraphQL in der Regel einen einzigen POST-Endpunkt verwendet, ist HTTP-Caching weniger effektiv als bei REST. Clients gleichen dies durch normalisierte Caches aus, und Server nutzen Persisted Queries sowie Response-Caching. Gestalte deine Mutations so, dass sie die geänderten Objekte zurückgeben, damit der Client-Cache konsistent bleibt.

GraphQL oder REST?

GraphQL spielt seine Stärken aus, wenn:

  • Clients für verschiedene Screens unterschiedliche Felder benötigen.
  • Ein Screen Daten aus vielen verwandten Ressourcen benötigt.
  • Sie eine einzige, typisierte und selbstdokumentierende API wünschen.

REST ist einfacher, wenn:

  • Ressourcen sauber auf Endpunkte abgebildet werden können.
  • HTTP-Caching und Status-Codes eine wichtige Rolle spielen.
  • Die API klein und stabil ist.

Viele Teams setzen beides ein: GraphQL für die Produkt-API und REST für Webhooks, Datei-Uploads und einfache öffentliche Endpunkte.

Best Practices

  • Entwerfen Sie das Schema basierend auf den Anforderungen des Clients, nicht auf den Datenbanktabellen.
  • Setzen Sie Non-Null-Typen bewusst ein und versionieren Sie das Schema mithilfe von Deprecations.
  • Halten Sie Resolver schlank und lagern Sie die Logik in Services aus.
  • Lösen Sie das N+1-Problem von Anfang an mit DataLoader.
  • Führen Sie Limits für die Query-Tiefe und Komplexität ein, um Missbrauch zu verhindern.
  • Geben Sie bei Mutations die geänderten Objekte zurück, um die Cache-Konsistenz zu gewährleisten.
  • Nutzen Sie in der Produktion Persisted Queries, um die Payload-Größe zu reduzieren.

Häufige Fehler

  • Das Datenbank-Schema direkt als GraphQL-Schema exponieren.
  • Das N+1-Problem zu ignorieren, bis die Performance einbricht.
  • In jeder Query alles abzufragen und damit den Hauptvorteil zu verlieren.
  • Sich auf vom Client übermittelte Autorisierungen oder Berechtigungen auf Feldebene zu verlassen.
  • Tief verschachtelte Queries ohne Depth Limit zu erlauben.
  • Davon auszugehen, dass HTTP-Caching genauso funktioniert wie bei REST.

Wie geht es weiter?

GraphQL ist ein leistungsstarker Weg, APIs an den Anforderungen der Clients auszurichten. Setzen Sie es auf dem HTTP-Protokoll auf, bauen Sie den Server mit Node.js und nutzen Sie ihn in React mithilfe einer Client-Library. Modellieren Sie anschließend einen Ihnen bekannten Screen als Schema und Query und erleben Sie, wie natürlich sich die Datenanforderungen abbilden lassen.

Daten abfragen

GraphQL gibt exakt die ausgewählten Felder zurück. REST-Endpoints liefern oft weit mehr zurück, als der Client benötigt, was Bandbreite und Parsing-Zeit verschwendet.

Bevorzugt
query {
  user(id: "1") {
    name
    avatar
  }
}
// only name and avatar
// cross the wire
Vermeiden
// GET /users/1 returns
// the entire user record,
// including fields the
// client never displays

Verknüpfte Daten abrufen

Eine einzige GraphQL-Query kann Beziehungen durchlaufen und vermeidet so die multiplen Roundtrips, die ein REST-Client machen müsste.

Bevorzugt
query {
  user(id: "1") {
    name
    posts(first: 3) {
      title
      comments { text }
    }
  }
}
Vermeiden
# three requests:
# /users/1
# /users/1/posts
# /posts/:id/comments

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, GraphQL zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch GraphQL — mit Quizzen und echtem Code, den Sie im Browser ausführen können.