Zum Inhalt springen
XMV Solutions logo
Developer reviewing a glowing API architecture diagram of endpoints and services. AI-generated image.
Zurück zum Blog

Eine API ist ein Vertrag. Oft schreibt ihn niemand.

Aron Strack·
api-designsoftware-architectureaienterprise

Die größten Probleme in Softwareprojekten entstehen selten im Code, sondern an den Schnittstellen zwischen Teams. Warum API-Design eine Architekturaufgabe ist, was passiert wenn man es den Entwicklern überlässt, und wie AI hilft, die Spezifikation endlich vor die Implementierung zu stellen.

Ein Muster, das ich über die Jahre in fast jedem größeren Projekt gesehen habe: Die wirklich teuren Probleme entstehen nicht im Code. Nicht in der Logik, nicht in der Technologiewahl. Sie entstehen an den Übergängen zwischen Systemen, genau dort, wo ein Team auf die Arbeit eines anderen angewiesen ist und beide Seiten eine andere Vorstellung davon haben, wie die Schnittstelle dazwischen aussieht.

Wie das anfängt

Ein Team bekommt eine fachliche Anforderung, irgendwann fällt der Satz „dafür brauchen wir eine API", und dann wird gebaut. Framework gewählt, ein paar Endpunkte definiert, Requests und Responses entstehen nebenbei während der Implementierung. Wirkt erstmal plausibel. Und parallel sitzt irgendwo ein anderes Team und wartet darauf, dass die Schnittstelle endlich nutzbar wird.

Was dann passiert, kennt vermutlich jeder, der schon in einem Multi-Team-Setup gearbeitet hat. Der eine Service gibt Preise als Number zurück, der andere als String. Ein Endpoint heißt /getProductData, der nächste folgt brav den REST-Konventionen. Es gibt kein DELETE /location/{id}, also schickt man als Workaround die komplette Liste minus den einen Eintrag, samt aller Race Conditions, die dazugehören. Fehlercodes sind technisch korrekt, helfen dem Consumer aber wenig, weil unklar bleibt, ob eine 400 gerade Validierung, Auth oder Business-Logik meint.

Einzeln ist das keine Katastrophe. Aber sobald mehrere Teams darauf aufbauen, summiert es sich. Ich habe Situationen erlebt, in denen ein Frontend-Team wochenlang blockiert war. Nicht weil die API fehlte, sondern weil sie sich dreimal geändert hat, bevor der erste Consumer sauber integriert war. Oder weil Felder auf einmal nullable waren, die es vorher nicht waren, und niemand das gesagt hat.

Besonders unangenehm wird es bei der Authentifizierung. OAuth2 und OpenID Connect sind theoretisch gut verstanden, in der Praxis sehe ich sie aber regelmäßig nur halb oder falsch umgesetzt. Dann wird eine „stärkere" Auth ergänzt, die alte bleibt aber als Default bestehen. Formal ist die Sicherheitsanforderung erfüllt, real hat sich am Angriffsprofil nichts geändert.

Warum das kein Entwicklerproblem ist

Die naheliegende Erklärung wäre: Die Entwickler machen schlechte Arbeit. Stimmt in den meisten Fällen aber nicht. Die Leute, mit denen ich arbeite, sind gut in ihrem Job. Sie kennen ihre Frameworks, sie bekommen Features zum Laufen, sie liefern. Was ihnen fehlt, ist die Erfahrung und ehrlich gesagt auch die Zuständigkeit, ein API-Design zu machen, das über das eigene Feature hinaus konsistent ist.

Das ist auch logisch. Ohne explizite Vorgaben trifft jedes Team seine eigenen Designentscheidungen. Jede kann für sich sinnvoll sein, nur passen sie nicht zusammen, weil sie unabhängig voneinander gefallen sind.

Irgendwann habe ich aufgehört, das als technisches Detail zu sehen. Ob ein Endpoint korrekt implementiert ist, ist am Ende zweitrangig. Die eigentliche Frage: Ist die Schnittstelle so definiert, dass drei andere Teams zuverlässig dagegen entwickeln können, ohne ständig nachfragen zu müssen? Das ist eine Architekturentscheidung. Eine API ist ein Vertrag, und Verträge schreibt man nicht nebenbei während der Implementierung. Zumindest nicht, wenn mehr als ein Team davon abhängt.

Innerhalb eines Teams reicht implizites Wissen. Man kennt die Konventionen, weiß wie die Kollegen denken, klärt Unklarheiten über den Tisch hinweg. Über Teamgrenzen hinweg, vor allem in größeren Enterprise-Setups mit mehreren Dienstleistern, braucht man explizite Vereinbarungen. Ab da skalieren informelle Absprachen nicht mehr, und man braucht einen echten, dokumentierten Vertrag.

Was AI daran ändert

Lange war das größte Hindernis hier schlicht der Aufwand. Eine wirklich saubere OpenAPI-Spezifikation zu schreiben, mit allen Feldern, Beispielen, Edge Cases und Error-Responses, dauert. Im Projektalltag wird das abgekürzt, weil der Druck da ist, schnell etwas Lauffähiges zu zeigen. Heraus kommt dann eine Spezifikation, die bestenfalls den Normalfall abdeckt. Oder, häufiger, gar keine, sondern nur die Implementierung als implizite Doku.

AI verschärft das zunächst sogar. Wenn Entwickler mit AI-Unterstützung schneller implementieren, entstehen inkonsistente Schnittstellen eben auch schneller. Schlechte Architektur skaliert mit.

AI macht aber auch eine Arbeitsweise möglich, die vorher zu aufwändig war. Ich arbeite inzwischen so: Ich beschreibe ein Feature fachlich, dazu die technischen Vorstellungen, die ich schon habe, und gehe damit in einen Dialog. Nicht „generier mir mal eine API", sondern iterativ. Ich lasse mir Rückfragen stellen, alternative Modellierungen vorschlagen, Edge Cases zeigen, die ich selbst noch nicht durchdacht hatte. Daraus wird eine vollständige OpenAPI-Spezifikation, mit Request- und Response-Beispielen, mit Error Cases, mit den richtigen HTTP-Methoden und Status Codes.

Die erste Version ist nie perfekt. Aber sie ist konkret genug, um darüber zu reden. Ich gehe sie durch, ändere was nicht passt, iteriere ein paar Runden, stimme sie mit den beteiligten Teams ab. Und der wichtige Teil: Das passiert alles, bevor die erste Zeile Implementierung steht.

Was danach anders läuft

Die Spezifikation landet dann nicht in irgendeinem Ordner, sondern wird aktiv benutzt. Sie geht ins Refinement, wird Teil der Tickets, gilt als verbindliche Grundlage. Teams entwickeln nicht mehr „auf eine API hin" und hoffen, dass sie irgendwann fertig wird, sondern gegen einen definierten Vertrag. Das implementierende Team und die Consumer arbeiten parallel, weil klar ist, wie die Schnittstelle aussehen wird.

Aus so einer Spezifikation lässt sich auch schnell ein Mock-Service erzeugen, der die grundlegenden Abläufe simuliert. Das reicht oft, um Integrationen früh zu testen, Wochen bevor die echte Implementierung steht.

Im Grunde dreht sich die Reihenfolge um. Schnittstellenentscheidungen, die früher implizit während der Implementierung fielen, verteilt über mehrere Teams und oft widersprüchlich, werden jetzt vorher getroffen und explizit festgehalten. Perfekt ist das nicht, es gibt immer Dinge, die sich erst später zeigen. Aber die Zahl der Überraschungen sinkt stark, und die Teams blockieren sich nicht mehr gegenseitig.

Die Prinzipien dahinter sind nicht neu. Klare Schnittstellen, explizite Verträge, frühe Validierung, das predigt die Softwarearchitektur seit Jahrzehnten. Gemacht hat es kaum jemand, weil der Aufwand zu hoch war. Das hat sich geändert. Wer heute noch Schnittstellen ohne expliziten Vertrag baut, entscheidet sich aktiv dafür, sich Probleme ins Projekt zu holen.