Um 02:14 Uhr läuft ein Aufruf in einen Timeout. Der nachgelagerte Dienst hat keine Antwort geliefert. Die Frage, die sich jeder Integrationsarchitekt als Nächstes stellen sollte, lautet nicht „Ist es fehlgeschlagen?“, sondern „Hat es geklappt, und ich weiß es nur nicht?“ Wie die AWS Builders' Library festhält, beweist ein Timeout nicht, dass die entfernte Operation fehlgeschlagen ist, denn das entfernte System kann die Arbeit durchaus erledigt haben, während die Antwort auf dem Weg verloren ging. Diese Mehrdeutigkeit ist die Wurzel der meisten Integrationsstörungen um 2 Uhr nachts. Nicht der Absturz. Die Ungewissheit.
Zu viele Teams behandeln Timeouts binär: Erfolg oder Fehler. Der Produktivbetrieb kennt diese Zweiteilung nicht. Ein Timeout erzeugt einen dritten Zustand, „unbekannter Ausgang“, und jede weitere Entscheidung (Retry? Kompensieren? Alarmieren?) hängt davon ab, wie die Architektur mit dieser Mehrdeutigkeit umgeht. Was nur im Happy Path funktioniert, funktioniert nicht.
Deshalb verdient das Thema mehr als eine Randnotiz in Ihren Architecture Decision Records. Mit dem Einzug KI-gesteuerter Workflows in die Integrationsschichten der Unternehmen wächst die Zahl ausgehender Aufrufe pro Geschäftsprozess. Mehr Aufrufe bedeuten mehr Stellen, an denen ein Timeout auftreten kann. Und mehr solche Stellen bedeuten mehr Ungewissheit um 2 Uhr nachts, es sei denn, die zugrunde liegenden Muster sind explizit, getestet und klar verantwortet. Die vier folgenden Muster (Timeouts, Retries, Idempotenz, Dead Letter Queues) bilden eine Kette von Abhängigkeiten. Lassen Sie eines weg, bricht das nächste.
Wie der Timeout-Wert gewählt wird, ist wichtiger, als die meisten Teams zugeben. Eine runde Zahl („sagen wir 5 Sekunden“) ist reine Raterei. Die AWS Builders' Library empfiehlt, den Wert an einem Latenzperzentil des nachgelagerten Dienstes auszurichten. Ein Beispiel: Wer die p99.9-Latenz des nachgelagerten Dienstes wählt, nimmt eine Rate von 0,1 % falscher Timeouts in Kauf. Das ist eine Designentscheidung, kein Standardwert. Und der Wert muss in die eigene Frist des Aufrufers passen. Setzen Sie für jeden ausgehenden Aufruf einen expliziten Timeout, bevor Sie überhaupt an Retry-Logik denken.
Retries wirken sicher. Ein Aufruf ist fehlgeschlagen, also versucht man es noch einmal. Die Logik ist intuitiv und funktioniert gut bei Fehlern, die wirklich vorübergehend sind: ein kurzer Netzwerkaussetzer, ein momentaner Ressourcenengpass. Gefährlich wird es, wenn der Fehler nicht vorübergehend ist oder wenn Hunderte Clients gleichzeitig einen Retry starten.
Das Muster ist einfach und brutal: Eine Abhängigkeit schwächelt, die Clients wiederholen ihre Aufrufe, das Retry-Volumen vervielfacht die Last auf dem ohnehin angeschlagenen Dienst, und aus einer teilweisen Beeinträchtigung wird ein vollständiger Ausfall. Unbegrenzte oder synchronisierte Retries können die Last verstärken und einen Ausfall verschlimmern. Der Retry sollte das Sicherheitsnetz sein. Stattdessen wurde er zum Brandbeschleuniger.
Drei Vorkehrungen verhindern das. Erstens: Retries begrenzen, also eine maximale Zahl von Versuchen und eine Gesamtfrist festlegen. Zweitens: exponentielles Backoff, bei dem jeder Retry länger wartet als der vorige und so den Druck auf den Dienst senkt, der sich erholt. Drittens: Jitter, also die Wartezeit zufällig streuen, damit nicht alle Clients im selben Augenblick wiederholen. Klingt selbstverständlich. In der Praxis bauen Teams zuerst Retries ein und entdecken die Lücke bei den Timeouts erst während einer Störung.
Und eines sollte man deutlich sagen: Bei Abläufen mit direktem Nutzerkontakt können weniger Retries mit schnellerem Scheitern und einem Fallback-Pfad besser sein als „wiederholen, bis es klappt“. Aggressive Retries erhöhen die Quote der Anfragen, die am Ende zugestellt werden, aber sie verlängern auch die Tail Latency, also die Latenz der langsamsten Anfragen. Wer auf ein Ladesymbol starrt, dem ist egal, dass die Anfrage beim vierten Versuch doch noch erfolgreich war, wenn es 40 Sekunden gedauert hat.
Gefährlich werden Retries in dem Moment, in dem die Operation Seiteneffekte hat. Eine GET-Anfrage, die dreimal wiederholt wird, ist lästig. Ein Zahlungsauftrag, der dreimal wiederholt wird, ist ein Rechtsstreit. Die Brücke zwischen „Retry für mehr Resilienz“ und „Retry ohne Schaden“ heißt Idempotenz: die Garantie, dass dieselbe Operation bei mehrfacher Ausführung dasselbe Ergebnis liefert wie bei einmaliger.
Der Mechanismus ist eine stabile Anfragekennung (ein Idempotenzschlüssel, englisch Idempotency Key), anhand derer der Server Duplikate erkennt. Stripe setzt Idempotenzschlüssel seit Jahren ein. Das Muster ist bekannt. Weniger bekannt sind die Kosten: Idempotenz erfordert persistenten Speicher für die Schlüssel, Aufbewahrungsregeln und eine Deduplizierungslogik, die gegen Race Conditions abgesichert ist. Umsonst ist das nicht. Für rein lesende Operationen können einfachere Retry-Regeln genügen. Für alles, was etwas anlegt, ändert oder abbucht, ist Idempotenz Pflicht.
Noch wichtiger wird das, wenn KI-gesteuerte Workflows in die Integrationsschicht einziehen. WSO2 hat einen Leitfaden zum Design idempotenter Tools speziell für agentenbasierte Architekturen veröffentlicht, weil LLM-gesteuerte Workflows Aktionen erneut auslösen können, wenn ein Schritt scheinbar fehlgeschlagen ist. Ein KI-Agent, der einen nicht idempotenten Tool-Aufruf wiederholt, weiß nicht, dass er damit den Seiteneffekt verdoppelt hat. Die Integrationsschicht ist dann nicht mehr bloße Verkabelung, sondern wird zur Steuerungsebene. Zeigen Sie mir erst das Rollback, dann die Demo.
Auch nach Timeouts, Retries und Idempotenz scheitern manche Nachrichten. Ein fehlerhaft aufgebauter Payload. Ein Verstoß gegen eine Geschäftsregel, den kein Retry behebt. Eine Abhängigkeit, die seit Stunden ausgefallen ist. Dead Letter Queues isolieren diese Nachrichten, damit sie den Hauptfluss nicht blockieren, nicht endlos wiederholt werden und nicht spurlos verschwinden.
Das Muster ist einfach. Der Betrieb ist es nicht. Eine DLQ ohne Alarm ist nur ein Ort, an dem Fehler in Vergessenheit geraten. Eine DLQ ohne Verantwortlichen ist ein Rückstau, der wächst, bis ihn jemand bei einem Audit bemerkt (oder bei einer Störung, je nachdem, was zuerst kommt).
Das Mindestmaß für eine DLQ umfasst vier Dinge: ein Monitoring, das alarmiert, sobald Nachrichten eintreffen, eine klare Zuständigkeit für die Triage, eine Aufbewahrungsregel, damit die Queue nicht unbegrenzt wächst, und einen getesteten Redrive-Mechanismus, der Nachrichten sicher erneut einspielen kann. Der letzte Punkt führt zurück zur Idempotenz: Wenn die erneut eingespielten Nachrichten nicht gefahrlos noch einmal ausgeführt werden können, schafft der Redrive neue Probleme, statt alte zu lösen.
Diese vier Muster hängen voneinander ab; sie sind kein Baukasten, aus dem man sich etwas aussucht. Die Reihenfolge in diesem Artikel erklärt die Abhängigkeiten, sie ist kein Bauplan für die Umsetzung. Timeouts begrenzen Retries: Ohne sie können Sie nicht festlegen, wie lange ein Retry läuft. Retries brauchen diese Klarheit über die Timeouts, sonst wissen Sie nicht, was Sie wiederholen und wie lange. Idempotenz muss stehen, bevor eine Operation mit Seiteneffekten überhaupt wiederholt wird, denn Retries ohne Deduplizierung erzeugen Duplikate. DLQs fangen auf, was die ersten drei Muster nicht lösen konnten.
Lassen Sie einen Schritt weg, bricht der nächste. Wer ohne Timeouts wiederholt, verlängert die Tail Latency und verdeckt zugleich, dass sich eine Abhängigkeit verschlechtert. Wer ohne Idempotenz wiederholt, erzeugt doppelte Abbuchungen. Wer DLQs ohne Monitoring betreibt, hat einen Fehlerfriedhof gebaut. Integrationsspezifische SLOs (Erfolgsquote beim ersten Versuch, Erfolgsquote nach allen Retries, Alter der Nachrichten in der DLQ) sind bessere Indikatoren als eine einzelne Verfügbarkeitszahl, denn Retries können eine verschlechterte Nutzererfahrung verdecken, wenn Sie nur messen, ob am Ende zugestellt wurde.
Architektur ist die Disziplin, die entscheidet, wo Fehler passieren dürfen. Diese vier Muster beseitigen Fehler nicht. Sie grenzen sie ein, machen sie sichtbar und verhindern, dass sie um 02:14 Uhr jemanden aus dem Schlaf reißen.


