Grundlagen

API-Stile

Wie Programme miteinander reden: REST, gRPC, GraphQL und Ereignisse im direkten Vergleich – wie viele Anfragen dieselbe Aufgabe braucht, wer die Felder bestimmt, und warum eine Kette synchroner Aufrufe so zerbrechlich ist.

Lesestand

Eine API ist ein Vertrag zwischen Programmen: Welche Anfragen gibt es, was muss man mitschicken, was kommt zurück. Vier Stile prägen die Praxis. REST denkt in Ressourcen mit Adressen und benutzt HTTP so, wie es gemeint ist. gRPC denkt in Funktionsaufrufen, binär und schnell. GraphQL lässt den Client genau die Felder anfordern, die er braucht. Ereignisse drehen das Verhältnis um: Ein Dienst verkündet, was passiert ist, und andere reagieren – ohne dass der Absender auf sie wartet.

Keiner ist allgemein besser. Entscheidend sind die Fragen: Wer ruft auf – ein Browser, eine App, ein anderer Dienst? Wie eng dürfen die Beteiligten aneinander gekoppelt sein? Und was passiert, wenn einer ausfällt?

Dieselbe Aufgabe, drei Stile

Eine App will Bestellung 42 anzeigen: mit Datum, dem Namen des Kunden und den Artikelnamen der Positionen. Wie viele Anfragen braucht das?

Bestellung 42 anzeigen
RESTgRPCGraphQL
DenkweiseRessourcen mit AdressenFunktionen aufrufeneinen Datengraphen abfragen
TransportHTTP, meist JSONHTTP/2, ProtobufHTTP, ein Endpunkt, JSON
VertragOpenAPI (optional).proto-Datei (Pflicht)GraphQL-Schema (Pflicht)
Cachingeingebaut über HTTPselbst lösenschwierig: alles ist ein POST
Streamingumständlicheingebaut, in beide Richtungenüber Subscriptions
Im Browserüberallnur über eine Brücke (gRPC-Web)überall
Typisch füröffentliche APIs, CRUDinterne Dienste untereinanderFrontends mit vielfältigem Datenbedarf

REST richtig verstanden

REST ist mehr als „JSON über HTTP“. Der Kern: Alles ist eine Ressource mit eigener Adresse (/bestellungen/42), und man arbeitet mit den einheitlichen HTTP-Methoden darauf – GET liest, PUT ersetzt, DELETE löscht. Substantive in der URL, Verben in der Methode: POST /bestellungen, nicht POST /legeBestellungAn. Weil REST HTTP so benutzt, wie es gedacht ist, funktionieren Caches, Proxys, Statuscodes und Werkzeuge einfach mit.

GraphQL: Der Client bestimmt

Bei REST legt der Server fest, was eine Antwort enthält. Bei GraphQL schreibt der Client eine Abfrage mit genau den Feldern, die er braucht – und bekommt genau die zurück:

Felder wählen

Der Preis liegt beim Server: Jede denkbare Kombination von Feldern muss effizient beantwortbar sein. Eine naive Umsetzung fragt für jede Position einzeln den Artikel ab – das N+1-Problem in neuem Gewand. Dagegen helfen „DataLoader“, die Einzelanfragen bündeln. Und weil Clients beliebig tiefe Abfragen bauen können, braucht ein öffentlicher GraphQL-Server Grenzen für Tiefe und Aufwand.

Synchron oder asynchron?

Bei REST, gRPC und GraphQL wartet der Aufrufer auf die Antwort – das ist synchron. Bei Ereignissen verkündet ein Dienst nur, was passiert ist („Bestellung 42 wurde aufgegeben“), über einen Nachrichtenvermittler. Wer sich dafür interessiert, reagiert, wann er kann. Der Unterschied zeigt sich, wenn etwas schiefgeht:

Eine Bestellung aufgeben

Synchrone Ketten sind leicht zu verstehen und zu debuggen, aber zerbrechlich: Ihre Verfügbarkeit ist das Produkt der Verfügbarkeiten aller Glieder, ihre Antwortzeit die Summe. Fünf Dienste mit je 99,9 % Verfügbarkeit ergeben zusammen nur noch 99,5 % – rund 44 Stunden Ausfall im Jahr statt knapp neun. Ereignisse entkoppeln: Der Absender muss die Empfänger nicht einmal kennen, und neue Empfänger kommen dazu, ohne dass er sich ändert. Der Preis ist Eventual Consistency – die Mail kommt vielleicht erst in einer Minute – und Abläufe, die schwerer nachzuvollziehen sind. Mehr dazu im Eintrag zu Messaging.

Eine leichte Form des Ereignisses über Systemgrenzen hinweg sind Webhooks: Ein externer Dienst ruft eine URL der eigenen Anwendung auf, wenn etwas passiert – etwa wenn eine Zahlung eingegangen ist. Weil jeder diese URL aufrufen könnte, prüft man eine Signatur, typischerweise einen HMAC aus der Kryptografie.

Verträge und Versionen

Eine API ist ein Versprechen an Programme, die man oft nicht kennt und nicht ändern kann. Deshalb gilt: Hinzufügen ist erlaubt, Wegnehmen und Umdeuten nicht.

ÄnderungKompatibel?
neues optionales Feld in der Antwort✓ – sofern Clients unbekannte Felder ignorieren
neuer Endpunkt, neue Methode✓
neues Pflichtfeld in der Anfrage✗ – alte Clients schicken es nicht
Feld umbenennen oder entfernen✗ – bei Protobuf ist Umbenennen harmlos, Entfernen nicht
Bedeutung oder Einheit ändern✗ – das schlimmste, weil es nicht sofort auffällt

Die Gegenseite heißt tolerant reader: Clients sollen nur lesen, was sie brauchen, und den Rest ignorieren. Für echte Brüche gibt es Versionen – /v2/bestellungen oder ein Header –, und die alte Version läuft eine Weile parallel weiter. Bewährt hat sich, den Vertrag zuerst zu schreiben (contract first) und Code daraus zu erzeugen: aus OpenAPI, der .proto-Datei oder dem GraphQL-Schema.

Für Entwickler übersetzt

// REST mit Spring
@RestController @RequestMapping("/bestellungen")
class BestellungController {
    @GetMapping("/{id}")  BestellungDto lade(@PathVariable long id) { … }
    @PostMapping        ResponseEntity<Void> lege(@RequestBody @Valid NeueBestellung b) { … }
}

// Deklarativer HTTP-Client (seit Spring 6): ein Interface, Spring baut die Implementierung
@HttpExchange("/kunden")
interface KundenClient {
    @GetExchange("/{id}") Kunde lade(@PathVariable long id);
}

// GraphQL mit Spring for GraphQL
@Controller
class BestellungGraph {
    @QueryMapping  Bestellung bestellung(@Argument long id) { … }
    @BatchMapping  Map<Bestellung, Kunde> kunde(List<Bestellung> bs) { … }  // gegen N+1
}

// Ereignis veröffentlichen, z. B. mit Spring for Apache Kafka
kafka.send("bestellungen", new BestellungAufgegeben(42, kundeId, summeCent));
WerkzeugWofür
springdoc-openapierzeugt aus Spring-Controllern eine OpenAPI-Beschreibung und eine Testoberfläche
OpenAPI Generatorerzeugt umgekehrt aus einer OpenAPI-Datei Client- und Server-Code
grpc-javaerzeugt aus .proto-Dateien Stubs für Client und Server
Spring for GraphQLSchema-first-GraphQL mit Annotationen, inklusive Batch-Laden
Problem Detailseinheitliche Fehlerantworten nach RFC 9457 – in Spring über ProblemDetail

Häufige Irrtümer

„REST heißt JSON über HTTP.“ – REST heißt Ressourcen, einheitliche Methoden und zustandslose Anfragen. Eine API mit POST /getKunde benutzt HTTP, ist aber kein REST.
„GraphQL macht REST überflüssig.“ – Es löst das Problem vielfältiger Clients elegant, erkauft das aber mit schwierigerem Caching, aufwendigerem Server und neuen Lastrisiken. Für einfache, stabile APIs ist REST oft die bessere Wahl.
„gRPC ist immer schneller.“ – Binär und mit dauerhafter Verbindung meist ja. Aber wenn die Datenbank 50 ms braucht, sind die eingesparten Mikrosekunden beim Parsen bedeutungslos.
„Asynchron ist moderner, also besser.“ – Es ist entkoppelter. Dafür muss man mit verzögerter Konsistenz, doppelten Nachrichten und schwer verfolgbaren Abläufen leben. Für eine Anfrage, auf deren Antwort der Nutzer wartet, ist synchron meist richtig.
„Mit /v1 in der URL ist Kompatibilität gelöst.“ – Die Version hilft nur bei bewussten Brüchen. Die meisten Probleme entstehen durch unbewusste – ein umbenanntes Feld, eine geänderte Einheit.

Verwandte Begriffe