GraphQL vs. REST
Zwei grundlegend unterschiedliche Ansätze, APIs zu gestalten - und welche Kriterien bei der Wahl zwischen beiden wirklich den Ausschlag geben.
Wer eine neue API plant, steht früher oder später vor der Frage: REST oder GraphQL? Beide Ansätze haben sich in der Praxis bewährt, lösen aber unterschiedliche Probleme unterschiedlich gut - und die Entscheidung lässt sich selten allein an der Technologie festmachen, sondern hängt stark davon ab, wie die API tatsächlich genutzt wird.
1. Wie REST Daten strukturiert
REST modelliert eine API als eine Menge von Ressourcen, die jeweils über eigene URLs erreichbar sind - etwa /users/42 oder /users/42/orders. Jeder Endpunkt liefert eine feste, vordefinierte Datenstruktur zurück, und die vier klassischen HTTP-Methoden (GET, POST, PUT/PATCH, DELETE) bilden die Operationen auf diesen Ressourcen ab. Das macht REST-APIs einfach zu verstehen, gut cachebar über Standard-HTTP-Mechanismen und leicht zu dokumentieren, weil jeder Endpunkt für sich beschrieben werden kann.
2. Wie GraphQL Daten strukturiert
GraphQL bietet stattdessen meist einen einzigen Endpunkt, über den Clients per Anfrage exakt festlegen, welche Felder und verknüpften Objekte sie benötigen. Ein streng typisiertes Schema definiert vorab, welche Felder und Beziehungen überhaupt existieren; die Anfrage selbst ist eine Art Beschreibung der gewünschten Antwortstruktur. Statt mehrerer Anfragen an verschiedene REST-Endpunkte lässt sich mit GraphQL oft eine einzige, präzise zugeschnittene Anfrage stellen, die genau die benötigten Daten in einer Antwort liefert - beide Formate übertragen die Antwort typischerweise als JSON.
3. Der entscheidende Unterschied: Over- und Under-Fetching
REST beantwortet die Frage “Welche vordefinierten Ressourcen gibt es?”, GraphQL beantwortet die Frage “Welche genauen Daten brauche ich gerade?”. Das führt bei REST zu zwei typischen Problemen: Over-Fetching, wenn ein Endpunkt mehr Felder liefert als der Client tatsächlich braucht (etwa das komplette Nutzerprofil, obwohl nur der Name angezeigt wird), und Under-Fetching, wenn für eine Ansicht mehrere Endpunkte nacheinander abgefragt werden müssen, weil die benötigten Daten über verschiedene Ressourcen verteilt sind. Bei stark vernetzten Datenmodellen mit vielen Beziehungen - etwa in sozialen Netzwerken oder komplexen Dashboards - vermeidet GraphQL dieses mehrfache Nachladen zusammengehöriger Daten.
4. Caching: REST im Vorteil
Ein oft unterschätzter Unterschied betrifft das Caching. REST-APIs profitieren direkt von HTTP-Standard-Caching-Mechanismen: Jede Ressourcen-URL kann individuell über HTTP-Header (Cache-Control, ETag) gecacht werden, und CDNs oder Browser-Caches greifen ohne Zusatzaufwand. GraphQL läuft dagegen meist über einen einzigen Endpunkt mit POST-Anfragen, wodurch das klassische URL-basierte HTTP-Caching nicht greift. GraphQL-Setups lösen das üblicherweise mit eigenen, clientseitigen Caching-Schichten (etwa in Apollo Client oder Relay) oder Persisted Queries - funktioniert gut, ist aber zusätzlicher Konfigurationsaufwand gegenüber dem, was bei REST quasi kostenlos mitkommt.
5. Fehlerbehandlung unterscheidet sich grundlegend
Bei REST signalisiert der HTTP-Statuscode selbst schon viel über den Ausgang einer Anfrage (404 für nicht gefunden, 403 für keine Berechtigung, 500 für Serverfehler). GraphQL-Antworten liefern dagegen bei den meisten Implementierungen unabhängig vom inhaltlichen Erfolg einen HTTP-Status 200 und packen Fehlerdetails in ein separates errors-Feld der Antwort. Das bedeutet: Monitoring- und Logging-Tools, die auf HTTP-Statuscodes reagieren, müssen für GraphQL-APIs oft angepasst werden, sonst bleiben inhaltliche Fehler unbemerkt.
6. N+1-Anfragen als typisches GraphQL-Problem
Ein Server-seitiges Problem, das gerade Teams beim Einstieg in GraphQL überrascht: Wenn ein Resolver für eine Liste von Objekten für jedes einzelne Objekt separat eine verknüpfte Ressource nachlädt (etwa den Autor zu jedem von 50 Blogposts), entstehen 50 einzelne Datenbankabfragen statt einer gebündelten - das sogenannte N+1-Problem. Es lässt sich lösen, etwa durch Batching/Dataloader-Muster, die mehrere angeforderte IDs gesammelt in einer Abfrage auflösen, ist aber ein Aufwand, den REST-APIs mit klassischem Resource-Loading in dieser Form seltener haben.
7. Rate-Limiting und Query-Komplexität
Bei REST lässt sich Rate-Limiting einfach pro Endpunkt konfigurieren, weil jeder Endpunkt eine bekannte, begrenzte Datenmenge liefert. Bei GraphQL kann eine einzelne, tief verschachtelte Anfrage theoretisch beliebig komplex werden und entsprechend viel Serverlast erzeugen - ein einfaches “Anfragen pro Minute”-Limit reicht daher oft nicht aus. GraphQL-Server begrenzen deshalb häufig zusätzlich die Verschachtelungstiefe oder berechnen eine Query-Komplexität, ab der eine Anfrage abgelehnt wird.
8. Wann REST die bessere Wahl ist
Für einfache, ressourcenorientierte APIs mit überschaubarer Datenstruktur bleibt REST oft die pragmatischere Wahl: geringere Komplexität auf Serverseite, kostenloses HTTP-Caching und eine breitere, seit Jahrzehnten etablierte Tooling-Landschaft. Auch für öffentliche APIs mit vielen externen Konsumenten ist REST häufig einfacher zu dokumentieren und für Drittentwickler zugänglicher.
9. Wann GraphQL die bessere Wahl ist
GraphQL lohnt sich besonders, wenn viele unterschiedliche Clients (z. B. Web, iOS, Android) mit stark abweichenden Datenanforderungen dieselbe API nutzen, oder wenn Over- und Under-Fetching bei REST spürbar zum Problem werden. Der Preis dafür ist höhere Komplexität beim Server-Setup, etwa bei Caching, Rate-Limiting und Query-Optimierung - Aufwand, der sich vor allem bei mehreren, datenmäßig sehr unterschiedlichen Clients auszahlt.
10. Hybride Ansätze
In der Praxis schließen sich beide Ansätze nicht aus: Manche Teams betreiben eine GraphQL-Schicht als Aggregations-Layer vor bestehenden REST-Diensten (ein sogenanntes Backend-for-Frontend-Muster), um Legacy-REST-APIs nicht komplett ablösen zu müssen. Auch der umgekehrte Fall kommt vor - einzelne, stark cachebare Ressourcen bleiben klassisch REST, während komplexe, stark verschachtelte Abfragen über GraphQL laufen.