REST vs GraphQL: Der ehrliche Vergleich mit eigenen Messungen (2026)

REST vs GraphQL: Der ehrliche Vergleich mit eigenen Messungen (2026)

Wer eine Schnittstelle baut oder anbindet, landet früher oder später bei dieser Frage: REST vs GraphQL — was ist besser? Im Netz findet man dazu zwei Lager. Das eine sagt, REST sei veraltet und GraphQL die Zukunft. Das andere sagt, GraphQL sei ein Hype, den außer Facebook niemand braucht. Beide liegen falsch, und zwar auf interessante Weise.

Die kurze Antwort: REST und GraphQL sind zwei Bauarten für Web-APIs. Bei REST gibt es viele Adressen (eine pro Ressource), und der Server bestimmt, was in der Antwort steht. Bei GraphQL gibt es eine einzige Adresse, und der Client beschreibt in einer Abfragesprache, welche Felder er haben will. Daraus folgt fast alles andere: GraphQL spart Anfragen und Datenmenge, REST ist einfacher zu cachen, abzusichern und zu betreiben.

Damit dieser Artikel nicht nur Meinungen wiederholt, haben wir am 13. Oktober 2026 zwei Dinge gemessen: dieselbe Aufgabe gegen die echte GitHub-API, die beide Varianten anbietet, und einen eigenen Testserver mit identischen Daten über REST und GraphQL. Drei Ergebnisse vorweg:

1. Ein Repository plus die letzten 10 Pull Requests plus Name und Follower-Zahl jedes Autors: REST brauchte 12 Anfragen, 248 KB und rund 3,5 Sekunden. GraphQL brauchte 1 Anfrage, 1,3 KB und rund 0,4 Sekunden.

2. Auf unserem eigenen Server schaffte ein einfacher REST-Endpunkt 44.671 Anfragen pro Sekunde, die gleichwertige GraphQL-Abfrage 6.075. GraphQL ist pro Anfrage teurer, weil jede Abfrage geparst und geprüft werden muss.

3. Eine 186 Byte kurze GraphQL-Abfrage brachte unseren ungeschützten Testserver dazu, 13 MB Antwort zu bauen und dafür 156.222 Datenbankzugriffe auszuführen. Bei REST gibt es dieses Problem in dieser Form nicht.

Links eine Reihe vieler kleiner leuchtender Türen mit je einem Briefumschlag davor, rechts ein einziges großes rundes Portal, in das ein Umschlag hineinfließt und ein passendes Paket herauskommt

REST vs GraphQL: Der grundlegende Unterschied

Wenn du noch nicht genau weißt, was eine Schnittstelle überhaupt ist, lies zuerst unseren Grundlagenartikel Was ist eine API?. Hier geht es um die Frage, wie man eine API baut.

So funktioniert REST

REST (Representational State Transfer) ist kein Protokoll und keine Software, sondern ein Architekturstil, den Roy Fielding im Jahr 2000 in seiner Doktorarbeit beschrieben hat. In der Praxis bedeutet „REST-API“ heute meistens:

  • Jede Ressource hat ihre eigene URL: /repos/withastro/astro, /users/octocat, /repos/withastro/astro/pulls.
  • Was du tun willst, steckt in der HTTP-Methode: GET liest, POST legt an, PUT/PATCH ändert, DELETE löscht.
  • Ob es geklappt hat, steht im Statuscode: 200, 201, 404, 401, 429 und so weiter.
  • Die Antwort ist meistens JSON, und der Server legt fest, welche Felder drinstehen.

Ein REST-Aufruf sieht so aus:

curl https://api.github.com/repos/withastro/astro

Zurück kommt ein JSON-Objekt mit über hundert Feldern: Name, Beschreibung, Sterne, Lizenz, Besitzer, Dutzende URLs zu weiteren Ressourcen. Ob du die brauchst oder nicht.

So funktioniert GraphQL

GraphQL wurde ab 2012 bei Facebook entwickelt, weil die mobile App für einen einzigen Bildschirm (den Newsfeed) zahlreiche REST-Anfragen über langsame Mobilfunknetze schicken musste. 2015 wurde es veröffentlicht, seit 2018 betreut es die GraphQL Foundation unter dem Dach der Linux Foundation.

Die Idee: Es gibt eine URL, meistens /graphql. Der Client schickt per POST eine Abfrage, die genau beschreibt, welche Daten er haben will, und bekommt eine Antwort in exakt dieser Form zurück:

{
  repository(owner: "withastro", name: "astro") {
    name
    stargazerCount
  }
}

Antwort:

{ "data": { "repository": { "name": "astro", "stargazerCount": 63194 } } }

Zwei Felder gefragt, zwei Felder bekommen. Hinter der Abfragesprache steht ein Schema, ein streng typisierter Bauplan aller Typen und Felder, die die API kennt. Der Server prüft jede Abfrage gegen dieses Schema, bevor er sie ausführt.

Die Unterschiede in einer Tabelle

RESTGraphQL
Adressenviele, eine pro Ressourcemeistens eine (/graphql)
Wer bestimmt die Felder?der Serverder Client
HTTP-MethodenGET, POST, PUT, PATCH, DELETEfast immer POST
Fehlerüber Statuscodes (404, 401 …)oft Status 200 mit errors-Feld
HTTP-Cachingeingebaut (ETag, Cache-Control, CDN)schwierig, meist im Client
Schemaoptional (OpenAPI)Pflicht, eingebaut
Versionierungoft /v1/, /v2/Felder als veraltet markieren
Echtzeitseparat (WebSockets, SSE)Subscriptions in der Spezifikation
Einstiegsehr leicht, ein curl reichtAbfragesprache, Schema, Resolver
Hauptrisikozu viele Anfragen, zu viele Datenteure Abfragen, N+1, Missbrauch

Unser Testaufbau

Gemessen haben wir an zwei Stellen, damit am Ende nicht nur ein künstliches Labor-Ergebnis steht.

Test 1: die echte GitHub-API. GitHub ist eines der wenigen großen Angebote, das dieselben Daten über REST (API v3) und GraphQL (API v4) liefert. Aufgabe: das Repository withastro/astro (auf dem übrigens auch getmind.io läuft), die letzten 10 geschlossenen Pull Requests und zu jedem Autor Name und Follower-Zahl. Abgefragt mit einem persönlichen Token von unserem Server in Nürnberg, dreimal hintereinander.

Test 2: ein eigener Server. Ein kleiner Node.js-Server (Node 22.23, graphql 17.0.2, graphql-http 1.23.1) mit 100 Autoren, 2.000 Beiträgen und 10.000 Kommentaren im Arbeitsspeicher. Dieselben Daten sind über REST-Endpunkte (/api/posts, /api/authors/:id) und über GraphQL erreichbar. Einmal mit naiven Resolvern, einmal mit Batching (dazu gleich mehr). Lastmessung mit autocannon 8.0.0: 16 gleichzeitige Verbindungen, je 10 Sekunden, auf einem 12-Kern-VPS, alles auf demselben Rechner.

Wichtig für die Einordnung: Test 2 misst den Overhead der Technik, nicht die Geschwindigkeit einer echten Datenbank. Die Daten liegen im RAM, das Netzwerk ist localhost. In echten Anwendungen ist die Datenbank fast immer der langsamste Teil, und die Unterschiede schrumpfen entsprechend.

Test 1: Wie viele Anfragen braucht eine Seite?

Stell dir eine Übersichtsseite vor: Repository-Name, Sternzahl, die letzten zehn Pull Requests, daneben der Name des Autors und wie viele Follower er hat. Ziemlich alltäglich.

Mit REST sieht das so aus:

  1. GET /repos/withastro/astro → Name und Sterne
  2. GET /repos/withastro/astro/pulls?state=closed&per_page=10 → zehn Pull Requests, aber vom Autor nur der Login-Name
  3. bis 12. GET /users/<login> → für jeden der zehn Autoren einzeln den vollen Namen und die Follower

Mit GraphQL ist es eine einzige Abfrage:

{
  repository(owner: "withastro", name: "astro") {
    name
    stargazerCount
    pullRequests(states: [CLOSED, MERGED], last: 10) {
      nodes {
        title
        number
        author {
          login
          ... on User { name followers { totalCount } }
        }
      }
    }
  }
  rateLimit { cost remaining }
}

Das Ergebnis aus drei Durchläufen:

RESTGraphQL
HTTP-Anfragen121
Antwortgröße (entpackt)247.806 Bytes1.324 Bytes
Gesamtdauer3.418 – 3.847 ms410 – 442 ms
Verbrauch am Kontingent12 von 5.000 pro Stunde1 von 5.000 Punkten pro Stunde

Zwölf kleine leuchtende Kugeln wandern auf einer Schleife zwischen zwei Säulen hin und her, daneben legt eine einzelne größere Kugel einen kurzen geraden Weg zurück

Die Zahl, die am meisten auffällt, ist die Größe: Faktor 187. Davon ist ein Teil Kosmetik, weil wir unkomprimiert gezählt haben und JSON sich gut packen lässt. Der Großteil ist aber echtes Overfetching: Jede REST-Antwort enthält dutzende Felder, die niemand angefordert hat, allein der Repository-Eintrag besteht überwiegend aus URLs zu weiteren Ressourcen.

Die Dauer kommt dagegen fast vollständig von den Rundreisen. Unser Skript hat die Anfragen nacheinander geschickt, wie es viele einfache Frontends tun. Jede Rundreise nach GitHub kostet rund 300 Millisekunden. Mit parallelen Anfragen ließe sich REST auf etwa drei Rundreisen drücken (Repo und Pull Requests gleichzeitig, danach die zehn Autoren gleichzeitig), aber nicht auf eine, weil man die Autoren erst kennt, wenn die Pull-Request-Liste da ist. Genau dieses Underfetching, also das Problem, dass eine Antwort nicht reicht und man nachladen muss, war der Grund, warum Facebook GraphQL erfunden hat.

Für eine Smartphone-App im Zug ist das kein theoretischer Unterschied. Zwölf Rundreisen über ein Netz mit 150 ms Latenz sind fast zwei Sekunden Wartezeit, bevor überhaupt etwas angezeigt wird.

Overfetching und Underfetching einfach erklärt

Diese beiden Begriffe tauchen in jedem REST-vs-GraphQL-Vergleich auf:

  • Overfetching: Du bekommst mehr Daten, als du brauchst. Du willst einen Namen und bekommst ein Objekt mit 100 Feldern.
  • Underfetching: Eine Antwort reicht nicht, du musst weitere Anfragen hinterherschicken. Du bekommst Pull Requests, aber zu den Autoren nur IDs.

REST kann beides abmildern, etwa mit Parametern wie ?fields=name,stars oder ?include=author. Viele große APIs bieten so etwas an. Das ist dann aber eine Eigenbau-Lösung pro API, während GraphQL es als Grundprinzip mitbringt.

Ein großer Würfel quillt über vor Dutzenden kleiner Kugeln, die auf den Boden rollen, daneben ein kleiner Würfel, der genau drei Kugeln ordentlich enthält

Test 2: Wie schnell ist ein einzelner Aufruf?

Jetzt die andere Seite. Auf unserem eigenen Server haben wir gemessen, wie viele Anfragen pro Sekunde jede Variante verarbeiten kann:

AufrufAnfragen pro SekundeLatenz p99
REST GET /api/authors/5 (ein Datensatz)44.671< 1 ms
GraphQL { post(id: 5) { title } } (ein Datensatz)6.0755 ms
REST GET /api/posts?limit=20 (20 Beiträge, 37 KB)16.3722 ms
GraphQL 20 Beiträge mit Autor, naiv5.0456 ms
GraphQL 20 Beiträge mit Autor, mit Batching4.0149 ms

Für einen einzelnen Datensatz ist REST auf unserem Server gut siebenmal schneller. Das liegt nicht daran, dass GraphQL schlecht programmiert wäre, sondern an der Arbeit, die es pro Anfrage zusätzlich macht: Abfragetext parsen, gegen das Schema validieren, für jedes einzelne Feld einen Resolver aufrufen und die Antwort in die angeforderte Form bringen. REST liefert ein fertiges Objekt per JSON.stringify aus.

Auffällig ist auch die letzte Zeile: Mit Batching war GraphQL auf unserem Testserver langsamer als naiv. Das klingt paradox, ist es aber nicht. Unsere „Datenbank“ ist ein Array im Arbeitsspeicher, ein Zugriff kostet praktisch nichts. Das Batching (Sammeln, Promise, Verteilen) kostet dagegen etwas. Bei einer echten Datenbank, wo jeder Zugriff eine Netzwerk-Rundreise ist, dreht sich das Bild sofort um. Darum geht es im nächsten Abschnitt.

Einordnung: 6.000 Anfragen pro Sekunde auf einem Prozess sind für fast jede Website mehr als genug. Unser ganzer Blog bekommt an einem Tag weniger Aufrufe, als dieser Server in einer Sekunde schafft. Der Overhead von GraphQL ist real, aber für die meisten Projekte nicht der Engpass.

Das N+1-Problem: GraphQLs bekannteste Falle

Wenn du „GraphQL langsam“ suchst, landest du fast immer hier. Das Problem entsteht durch die Art, wie GraphQL-Server Abfragen ausführen: Jedes Feld hat einen eigenen Resolver, eine kleine Funktion, die genau dieses Feld besorgt. Für die Abfrage

{ posts(limit: 20) { title author { name } } }

läuft das naiv so ab:

  1. Ein Resolver holt die 20 Beiträge → 1 Datenbankabfrage
  2. Für jeden der 20 Beiträge holt der author-Resolver den Autor → 20 Datenbankabfragen

Macht 21 Abfragen für eine Liste. Daher der Name: 1 für die Liste, plus N für jedes Element. Genau das haben wir in unserem Testserver gezählt:

VarianteDatenbankzugriffe für 20 Beiträge mit Autor
GraphQL, naive Resolver21
GraphQL mit Batching (DataLoader-Prinzip)2

Die übliche Lösung heißt DataLoader, ursprünglich auch von Facebook. Statt sofort die Datenbank zu fragen, sammelt der Resolver alle angefragten IDs bis zum Ende des aktuellen Durchlaufs und schickt dann eine Abfrage WHERE id IN (…). Unser Testserver macht das mit etwa zehn Zeilen Code, in echten Projekten nimmt man die fertige Bibliothek dataloader.

Wichtig: N+1 ist kein reines GraphQL-Problem. Jedes ORM, jedes Template, das in einer Schleife nachlädt, kann es auslösen, auch in einer REST-API. Der Unterschied ist, dass bei REST der Server-Entwickler die Abfragen eines Endpunkts kennt und einmal optimieren kann. Bei GraphQL kann jeder Client neue Kombinationen schicken, an die beim Bau niemand gedacht hat.

Die 186-Byte-Abfrage: Wo GraphQL gefährlich wird

Jetzt wird es ernst. In unserem Schema verweist ein Beitrag auf seine Kommentare, und jeder Kommentar zurück auf seinen Beitrag. Das ist völlig normal und in fast jedem echten Datenmodell so. Aber es erlaubt Abfragen wie diese:

{
  posts(limit: 20) {
    comments {
      post { comments {
        post { comments {
          post { comments { text } }
        } }
      } }
    }
  }
}

Jede zusätzliche Ebene vervielfacht die Arbeit. Wir haben das Schritt für Schritt gegen unseren Server ohne Schutzmaßnahmen geschickt (Batching für Autoren war aktiv, half hier aber nicht, weil Kommentare pro Beitrag geladen werden):

VerschachtelungstiefeAbfragegrößeAntwortgrößeDatenbankzugriffeDauer
178 Bytes19.920 Bytes22120 ms
2105 Bytes103.420 Bytes1.22153 ms
3132 Bytes520.920 Bytes6.221185 ms
4159 Bytes2.608.420 Bytes31.221270 ms
5186 Bytes13.045.920 Bytes156.2221.269 ms

Jede Ebene mal fünf. Eine Anfrage, die kürzer ist als dieser Absatz, ließ unseren Server über eine Sekunde rechnen und 13 MB Antwort bauen. Eine sechste Ebene wäre bei rund 65 MB und 780.000 Zugriffen gelandet; die haben wir uns gespart. Zehn solcher Anfragen pro Sekunde reichen, um einen kleinen Server lahmzulegen, und dafür braucht man keine Botnetze, sondern einen einzigen Laptop.

Ein kleiner Kieselstein fällt in einen ruhigen Teich und löst eine riesige, sich verzweigende Welle aus leuchtenden Ästen aus

Bei REST gibt es dieses Problem in dieser Form nicht: Ein Endpunkt liefert immer dieselbe, vom Server festgelegte Menge. Wer REST angreifen will, muss viele Anfragen schicken, und viele Anfragen erkennt jeder Rate Limiter sofort.

So schützt man eine GraphQL-API

Das Problem ist bekannt und lösbar, aber eben nicht automatisch gelöst. Was in der Praxis hilft:

  1. Tiefenbegrenzung: Abfragen mit mehr als z. B. 7 Ebenen werden abgelehnt (Bibliotheken wie graphql-depth-limit).
  2. Kostenberechnung: Jedes Feld bekommt Kosten, Listen werden mit ihrer maximalen Länge multipliziert, und zu teure Abfragen werden vor der Ausführung abgelehnt. GitHub macht genau das: Unsere Abfrage oben kostete laut Antwort 1 Punkt von 5.000 pro Stunde. Wer Listen mit 100 Elementen in 100 Elementen abfragt, zahlt entsprechend mehr.
  3. Pflicht-Limits für Listen: Kein Listenfeld ohne first/last, mit Obergrenze (GitHub: maximal 100).
  4. Persisted Queries: In der eigenen App sind die Abfragen beim Bauen bekannt. Man speichert sie auf dem Server und erlaubt nur noch diese, der Client schickt bloß eine ID. Damit ist das Thema für interne APIs praktisch erledigt.
  5. Zeitlimits für die Ausführung jeder Abfrage.

Introspection: Die API erklärt sich selbst

GraphQL hat eine eingebaute Funktion, mit der jeder Client das komplette Schema abfragen kann:

{ __schema { types { name } } }

Unser Testserver lieferte daraufhin bereitwillig alle Typen, Felder und Beziehungen. Für Entwickler ist das großartig: Werkzeuge wie GraphiQL bieten damit Autovervollständigung und Dokumentation, ohne dass jemand eine Zeile Doku schreibt. Für Angreifer ist es ein Lageplan. In Produktion schalten viele Betreiber Introspection deshalb ab, wenn die API nicht öffentlich sein soll. Absicherung ist das trotzdem nicht: Schon die Fehlermeldungen helfen weiter. Auf { post(id: 5) { titel } } antwortete unser Server: „Cannot query field “titel” on type “Post”. Did you mean “title”?”

Dass Angreifer gezielt nach GraphQL-Schnittstellen suchen, sehen wir in unseren eigenen Logs. Unser Blog hat überhaupt keine API, trotzdem kamen zwischen 7. September und 12. Oktober 2026 309 Anfragen an /graphql, 174 an /api/graphql und 167 an /v1/graphql. Die Details stehen im API-Artikel.

Caching: Der größte praktische Vorteil von REST

REST nutzt HTTP so, wie es gedacht war. Ein GET auf eine URL ist eine Leseanfrage, und das ganze Internet (Browser, Proxys, CDNs, Reverse Proxys) weiß, wie man so etwas zwischenspeichert. Wir haben es an GitHub ausprobiert:

  • REST: Die Antwort auf GET /repos/withastro/astro enthielt einen ETag und Cache-Control: private, max-age=60, s-maxage=60. Beim zweiten Aufruf mit If-None-Match kam 304 Not Modified, also keine Daten, nur die Bestätigung, dass sich nichts geändert hat.
  • GraphQL: Die Antwort auf eine POST-Abfrage an /graphql enthielt weder ETag noch Cache-Control. Kein Zwischenspeicher der Welt cached POST-Anfragen von sich aus.

Bei GraphQL wandert das Caching deshalb in den Client. Bibliotheken wie Apollo Client oder urql speichern die Ergebnisse normalisiert nach Typ und ID und wissen, welche Komponenten neu gezeichnet werden müssen. Das funktioniert gut, ist aber deutlich mehr Logik, als einen Header zu setzen. Serverseitig gibt es Lösungen über GET-Abfragen mit Persisted Queries (unsere Testbibliothek akzeptierte GET /graphql?query=… problemlos mit 200), aber das ist Zusatzarbeit, die man bewusst einbauen muss.

Für eine öffentliche API mit vielen anonymen Lesern ist das oft der entscheidende Punkt: Eine REST-Antwort, die ein CDN eine Minute lang ausliefert, verursacht in dieser Minute null Last auf deinem Server.

Fehlerbehandlung: 404 oder 200?

Wir haben dieselbe nicht existierende Ressource bei GitHub über beide Wege abgefragt:

  • REST: GET /repos/withastro/nope-xyz → HTTP 404.
  • GraphQL: repository(owner: "withastro", name: "nope-xyz") → HTTP 200, im Body "repository": null und ein errors-Array mit "type": "NOT_FOUND".

Das ist kein GitHub-Fehler, sondern so vorgesehen: Eine GraphQL-Abfrage kann zehn Dinge gleichzeitig anfragen, von denen neun klappen. Ein einzelner Statuscode kann das nicht ausdrücken. Für dich als Entwickler heißt das aber: Monitoring, das nur auf Statuscodes schaut, sieht bei GraphQL keine Fehler. Dein Dashboard zeigt 100 % grüne 200er, während die Hälfte der Antworten errors enthält. Man muss den Body auswerten.

Neuere Server halten sich inzwischen an den Entwurf „GraphQL over HTTP“: Wer den Medientyp application/graphql-response+json anfordert, bekommt bei ungültigen Abfragen einen echten Statuscode. Unser Testserver antwortete auf die Tippfehler-Abfrage dann mit 400 Bad Request statt 200. Auf diesen Standard kann man sich aber noch nicht bei jeder API verlassen.

Rate Limits: Anfragen zählen oder Kosten zählen?

Bei REST ist ein Rate Limit einfach: so und so viele Anfragen pro Stunde. GitHub erlaubt mit Token 5.000. Unser REST-Durchlauf hat jedes Mal 12 davon verbraucht (Kontingent sank von 5.000 auf 4.988, 4.976, 4.964).

Bei GraphQL funktioniert das nicht, weil eine einzelne Anfrage harmlos oder verheerend sein kann. GitHub rechnet deshalb in Punkten: Die Kosten einer Abfrage werden vor der Ausführung geschätzt, und die Antwort sagt dir, was sie gekostet hat (rateLimit { cost remaining }). Unsere Abfrage: 1 Punkt. Der Haken: Solche Kostenmodelle muss jeder GraphQL-Anbieter selbst bauen, und für Nutzer sind sie schwerer vorherzusehen als „eine Anfrage = eins“.

Ein Detail am Rande, das uns überrascht hat: Ohne Token antwortet GitHubs GraphQL-API überhaupt nicht, sondern mit 403 und x-ratelimit-limit: 0. Die REST-API erlaubt anonym immerhin 60 Anfragen pro Stunde. Wer schnell etwas ausprobieren will, kommt mit REST also ohne Anmeldung weiter.

Versionierung und Weiterentwicklung

REST-APIs werden oft über die URL versioniert: /v1/users, /v2/users. Das ist simpel und eindeutig, bedeutet aber, dass man mehrere Versionen parallel betreiben muss, bis der letzte alte Client verschwunden ist. Viele APIs nutzen inzwischen stattdessen Datums-Versionen per Header.

GraphQL verzichtet bewusst auf Versionen. Neue Felder kann man jederzeit hinzufügen, weil kein bestehender Client sie anfragt. Alte Felder markiert man mit @deprecated und schaut im Log, wer sie noch benutzt. Weil jeder Client genau sagt, welche Felder er liest, weiß der Betreiber sehr genau, was er entfernen kann. Das ist ein echter Vorteil, wenn viele verschiedene Apps dieselbe API nutzen.

Entwicklererfahrung: Was sich im Alltag anders anfühlt

Für REST spricht:

  • Jeder kann es sofort ausprobieren: Browser, curl, Postman, fertig.
  • Jede Sprache und jedes Framework hat es eingebaut. Ein REST-Endpunkt in Express, Laravel oder Django ist eine Handvoll Zeilen.
  • Logs, Monitoring, Firewalls und Rate Limiter verstehen URLs und Statuscodes von Haus aus.
  • Datei-Uploads und -Downloads sind einfach, weil HTTP dafür gemacht ist. Bei GraphQL braucht man dafür Erweiterungen.

Für GraphQL spricht:

  • Das Schema ist die Dokumentation und immer aktuell.
  • Mit Code-Generatoren bekommst du aus dem Schema automatisch TypeScript-Typen für jede Abfrage. Tippfehler in Feldnamen fallen beim Bauen auf, nicht beim Kunden.
  • Frontend-Teams können neue Ansichten bauen, ohne auf neue Endpunkte vom Backend zu warten.
  • Mehrere Quellen (Datenbank, Microservices, externe APIs) lassen sich hinter einer Schnittstelle zusammenführen.

Für REST spricht auch: OpenAPI (früher Swagger) schließt die Lücke beim Schema inzwischen weitgehend. Auch daraus kann man Typen und Clients generieren. Der Abstand ist kleiner, als viele GraphQL-Artikel behaupten.

Das Video von „the native web“ ist von 2020, also älter. An den Grundprinzipien hat sich seitdem nichts geändert, und es ist eine der gründlichsten deutschsprachigen Erklärungen. Weiter unten folgt eine aktuelle englische Einordnung, die auch gRPC mit einbezieht.

Und gRPC? Die dritte Option

In Vergleichen taucht oft noch ein Dritter auf: gRPC, ursprünglich von Google. Hier werden Daten nicht als JSON-Text, sondern binär (Protocol Buffers) über HTTP/2 übertragen, und Client und Server teilen sich eine fest definierte Schnittstellenbeschreibung. Das ist sehr schnell und kompakt, aber im Browser nur über Umwege nutzbar.

Grob kann man sich merken: REST für öffentliche und einfache APIs, GraphQL für Frontends mit komplexen Datenanforderungen, gRPC für die Kommunikation zwischen Diensten im eigenen Rechenzentrum. Viele große Firmen nutzen alle drei gleichzeitig.

Englisch, Mai 2026: ein Überblick über REST, GraphQL und gRPC mit Entscheidungshilfen aus der Praxis.

Wer nutzt was? Ein Blick in bekannte Systeme

  • GitHub bietet beides an, REST und GraphQL. Neue Funktionen erscheinen oft zuerst in GraphQL.
  • Shopify hat GraphQL zur bevorzugten Schnittstelle gemacht, die REST-Admin-API gilt dort als Altlast.
  • Shopware setzt auf REST (Store API und Admin API) mit einem eigenen Such-Format, das Felder und verknüpfte Daten auswählbar macht. Ein gutes Beispiel dafür, wie REST die Vorteile von GraphQL teilweise nachbaut. Mehr zum System im Vergleich Shopify vs Shopware.
  • Magento/Adobe Commerce hat sowohl REST als auch GraphQL; die Storefront-Seite läuft zunehmend über GraphQL. Die Inhalte des Magento-CMS sind ebenfalls per GraphQL abrufbar, das haben wir uns im Artikel Magento CMS genauer angeschaut.
  • Stripe, Twilio und fast alle Zahlungs- und Kommunikationsdienste setzen auf REST, weil sie von tausenden unterschiedlichen Kunden in allen Sprachen angebunden werden.
  • WordPress hat eine REST-API eingebaut; GraphQL gibt es über das Plugin WPGraphQL, besonders beliebt für Headless-Setups.

Ein ehrlicher Satz zu unserem eigenen Alltag: Die Dienste auf unserem Hauptserver sprechen fast ausschließlich REST. Für eine Handvoll Endpunkte, ein bekanntes Frontend und überschaubare Datenmodelle wäre GraphQL mehr Aufwand als Nutzen gewesen. Wo wir GraphQL nutzen, ist es fast immer, weil ein fremdes System (wie GitHub) es anbietet und wir dort viele verknüpfte Daten auf einmal brauchen.

Wann REST, wann GraphQL? Die Entscheidung

Eine Person steht an einer Weggabelung, ein Weg führt zu einer Reihe schlichter ordentlicher Briefkästen, der andere zu einem leuchtenden Knotenpunkt mit vielen Kabeln

Nimm REST, wenn …

  • die API öffentlich ist und von vielen unterschiedlichen Kunden genutzt wird,
  • viele Leser dieselben Daten abfragen und HTTP-Caching oder ein CDN viel Last abnehmen kann,
  • die Datenmodelle überschaubar sind und die Seiten nicht zehn Ressourcen gleichzeitig brauchen,
  • du Dateien überträgst,
  • dein Team klein ist und Betrieb, Monitoring und Sicherheit einfach bleiben sollen,
  • du gerade erst anfängst, APIs zu bauen.

Nimm GraphQL, wenn …

  • mehrere Frontends (Web, iOS, Android) dieselben Daten in unterschiedlicher Form brauchen,
  • Seiten Daten aus vielen verknüpften Ressourcen zusammensetzen,
  • mobile Nutzer über langsame Netze kommen und jede Rundreise zählt,
  • Frontend- und Backend-Teams unabhängig voneinander arbeiten sollen,
  • du mehrere Dienste hinter einer Schnittstelle bündeln willst,
  • du bereit bist, Tiefenbegrenzung, Kostenberechnung und Batching ordentlich einzurichten.

Beides geht auch. Sehr verbreitet ist: REST nach außen für Partner und Integrationen, GraphQL nach innen als Datenschicht für die eigenen Apps. Oder ein „Backend for Frontend“, das intern mehrere REST-Dienste abfragt und dem Frontend genau das liefert, was es braucht.

Checkliste: REST oder GraphQL in sechs Fragen

  1. Wer nutzt die API? Fremde Entwickler in vielen Sprachen → eher REST. Die eigenen Apps → GraphQL lohnt sich eher.
  2. Wie viele Ressourcen braucht eine typische Ansicht? Eine bis zwei → REST. Fünf und mehr, verschachtelt → GraphQL.
  3. Können die Antworten gecacht werden? Ja, für viele Nutzer gleich → großer Pluspunkt für REST.
  4. Wie langsam ist das Netz der Nutzer? Mobilfunk, Schwellenländer → GraphQL spart spürbar Zeit.
  5. Wer betreibt das System? Ein kleines Team ohne Zeit für Absicherung → REST. Ein Team, das Kostenlimits und Monitoring einrichtet → GraphQL ist machbar.
  6. Welche Werkzeuge gibt es schon? Wenn dein Framework oder Shopsystem eine der beiden Varianten gut unterstützt, nimm die.

Häufige Fragen zu REST vs GraphQL

Was ist der Unterschied zwischen REST und GraphQL?

REST stellt viele Adressen bereit, eine pro Ressource, und der Server bestimmt, welche Daten zurückkommen. GraphQL stellt meistens eine einzige Adresse bereit, und der Client beschreibt mit einer Abfragesprache genau, welche Felder er haben möchte. Dadurch braucht GraphQL weniger Anfragen und überträgt weniger überflüssige Daten, während REST einfacher zu cachen und abzusichern ist.

Ist GraphQL schneller als REST?

Es kommt darauf an, was man misst. Für eine Seite, die viele verknüpfte Daten braucht, war GraphQL in unserem Test gegen GitHub rund achtmal schneller (1 statt 12 Anfragen). Für einen einzelnen Datensatz war REST auf unserem eigenen Server rund siebenmal schneller, weil GraphQL jede Abfrage parsen und prüfen muss. GraphQL spart Rundreisen, REST spart Rechenzeit pro Anfrage.

Ist GraphQL besser als REST?

Nein, es ist anders. GraphQL löst die Probleme von Over- und Underfetching und eignet sich hervorragend für komplexe Frontends. Dafür sind Caching, Rate Limiting, Fehlerbehandlung und Absicherung aufwendiger. Für öffentliche, einfache oder stark gecachte APIs ist REST meist die bessere Wahl.

Ersetzt GraphQL REST?

Nein. Laut Postmans Entwicklerumfrage 2025 (zitiert nach WunderGraph) nutzt die große Mehrheit der Entwickler weiterhin REST, GraphQL wird von etwa einem Drittel eingesetzt, meistens zusätzlich. In der Praxis laufen beide nebeneinander, oft sogar im selben Unternehmen.

Ist GraphQL ein Datenbank-System?

Nein, auch wenn der Name das nahelegt („QL“ wie in SQL). GraphQL ist eine Abfragesprache für APIs. Woher die Daten kommen, entscheiden die Resolver auf dem Server: aus einer Datenbank, aus anderen APIs, aus Dateien oder aus allem gleichzeitig.

Kann man GraphQL und REST zusammen verwenden?

Ja, und das ist sehr häufig. Viele Firmen bieten nach außen eine REST-API an und nutzen intern GraphQL als Datenschicht für die eigenen Apps. Ein GraphQL-Server kann auch selbst bestehende REST-Dienste abfragen und deren Daten zusammenführen.

Was ist das N+1-Problem bei GraphQL?

Wenn eine Liste mit 20 Einträgen abgefragt wird und zu jedem Eintrag ein verknüpftes Objekt, holen naive Resolver erst die Liste (1 Abfrage) und dann jedes Objekt einzeln (20 Abfragen). In unserem Test waren das 21 Datenbankzugriffe statt 2. Die Lösung ist Batching, etwa mit der Bibliothek DataLoader, die alle IDs sammelt und in einer Abfrage holt.

Ist GraphQL unsicherer als REST?

Nicht grundsätzlich, aber es hat eigene Risiken. Weil Clients beliebige Abfragen bauen können, kann eine kurze, tief verschachtelte Abfrage enorme Last erzeugen. In unserem Test erzeugten 186 Bytes 13 MB Antwort und über 156.000 Datenbankzugriffe. Mit Tiefenbegrenzung, Kostenberechnung, Listenlimits und Persisted Queries ist das beherrschbar, muss aber aktiv eingerichtet werden.

Kann man GraphQL-Antworten cachen?

Ja, aber nicht so einfach wie bei REST. Weil GraphQL fast immer POST verwendet, greifen Browser-Caches und CDNs nicht von selbst. Gecacht wird meist im Client (Apollo, urql) oder auf dem Server über Persisted Queries mit GET-Anfragen. Bei REST reichen oft ein paar HTTP-Header.

Welche HTTP-Statuscodes nutzt GraphQL?

Klassisch antwortet ein GraphQL-Server fast immer mit 200, auch bei Fehlern, und schreibt die Fehler in ein errors-Feld im JSON. Neuere Server nach dem Standardentwurf „GraphQL over HTTP“ liefern bei ungültigen Abfragen 400 und andere passende Codes, wenn der Client den Typ application/graphql-response+json anfordert.

Was sollte ein Anfänger zuerst lernen, REST oder GraphQL?

REST. Es baut direkt auf HTTP auf, du kannst jeden Schritt mit dem Browser oder curl nachvollziehen, und fast jede API, mit der du in Berührung kommst, nutzt es. Wer REST versteht, versteht auch schneller, welche Probleme GraphQL löst. Einen Einstieg gibt unser Artikel Was ist eine API?, für das Datenformat dahinter Was ist eine JSON-Datei?.

Fazit

Die Frage „REST vs GraphQL“ hat keine allgemeine Antwort, aber eine sehr gute für deinen Fall, wenn du die richtigen Dinge misst. Unsere Messungen zeigen die Gegensätze deutlich: GraphQL holte eine verschachtelte Ansicht in 1 statt 12 Anfragen, mit 1,3 statt 248 KB und in einem Achtel der Zeit. Dafür war REST pro einzelner Anfrage rund siebenmal schneller, lässt sich mit einem Header cachen, meldet Fehler über Statuscodes und kennt die 186-Byte-Abfrage nicht, die einen ungeschützten GraphQL-Server über eine Sekunde beschäftigt.

Unsere Empfehlung: Starte mit REST, solange du keinen konkreten Grund für GraphQL hast. Dieser Grund ist meistens einer von dreien: mehrere Apps mit unterschiedlichen Datenbedürfnissen, Ansichten aus vielen verknüpften Ressourcen oder Nutzer mit langsamen Verbindungen. Wenn einer davon zutrifft, ist GraphQL eine hervorragende Wahl. Dann aber mit Tiefenlimit, Kostenberechnung und DataLoader von Anfang an, nicht erst nach dem ersten Ausfall.