Retries: warum automatische Wiederholungen Ausfälle verschlimmern
Ein automatischer Wiederholungsversuch gilt als simples Sicherheitsnetz gegen unzuverlässige Schnittstellen. In Wahrheit verstärken naive Retries Ausfälle, verschicken Duplikate und verbrennen Kontingente. Was wir Kunden über Backoff, Idempotenz und Circuit Breaker erklären, bevor wir den Haken setzen.
Der Abend, an dem eine Wiederholung 40.000 E-Mails verschickte
Im März bekamen wir gegen 21 Uhr einen Anruf. Ein Kunde, Onlinehändler mit angeschlossenem Großhandel, hatte ein Problem: Kunden meldeten sich, weil sie dieselbe Versandbestätigung sieben, acht, teils zwölf Mal erhalten hatten. Der Support lief heiß. In den Bewertungen tauchten die ersten wütenden Kommentare auf.
Die Ursache war schnell gefunden und trotzdem lehrreich. Ein Workflow schickte nach jedem Versand eine Bestätigungsmail über einen externen Mailanbieter. Der Anbieter hatte an diesem Abend Latenzprobleme, Antworten kamen langsam oder liefen in einen Timeout. Und die Automatisierungsplattform tat, was sie standardmäßig tut, wenn ein Schritt keine saubere Antwort bekommt: Sie versuchte es erneut. Und weil der Timeout länger dauerte als das eingestellte Intervall, stapelten sich die Wiederholungen. Aus einer Mail wurden acht. Bei tausenden offenen Bestellungen wurden aus ein paar tausend Mails über den Abend verteilt rund 40.000.
Das Bittere daran: Der Mailanbieter war gar nicht komplett ausgefallen. Er war nur langsam. Jede einzelne Mail wurde tatsächlich verschickt. Der Timeout log dem Workflow vor, es sei nichts passiert, also schickte er nach. Die Wiederholung, die das System retten sollte, hat den Schaden erst erzeugt.
Wir sehen diese Klasse von Fehlern regelmäßig, und fast immer steckt derselbe Denkfehler dahinter. Retries, also automatische Wiederholungsversuche, gelten als das simple Sicherheitsnetz gegen unzuverlässige Schnittstellen. In Wahrheit sind sie eines der schärfsten Werkzeuge im ganzen Automatisierungsbaukasten, und wer sie ohne Nachdenken einschaltet, baut sich einen Fehlerverstärker statt einer Absicherung.
Dieser Artikel ist die lange Version dessen, was wir Kunden erklären, bevor wir irgendwo den Haken bei "bei Fehler automatisch wiederholen" setzen.
Was ein Retry eigentlich voraussetzt
Ein Retry ist eine Wette. Die Wette lautet: Der Vorgang ist beim ersten Mal fehlgeschlagen, aber die Ursache ist vorübergehend, und beim zweiten Versuch klappt es. Damit diese Wette aufgeht, müssen zwei Dinge stimmen.
Erstens muss der Fehler wirklich vorübergehend sein. Ein Netzwerkabbruch, eine kurz überlastete Datenbank, ein Rate-Limit für ein paar Sekunden, das sind Situationen, in denen ein zweiter Versuch Sinn ergibt. Ein falsches Passwort, eine ungültige Rechnungsnummer, ein Pflichtfeld, das fehlt, das sind sie nicht. Diese Fehler wiederholen sich beliebig oft mit demselben Ergebnis, nur dass jeder Versuch Zeit und Kontingent kostet.
Zweitens, und das ist die Bedingung, die fast alle übersehen, muss der Vorgang gefahrlos wiederholbar sein. Wenn der erste Versuch vielleicht schon etwas bewirkt hat, bevor er scheinbar scheiterte, dann macht die Wiederholung diese Wirkung ein zweites Mal. Genau das ist im Fall unseres Onlinehändlers passiert. Die Mail ging raus, nur die Bestätigung darüber kam nicht zurück.
Für diese gefahrlose Wiederholbarkeit gibt es einen Fachbegriff, den wir in einem eigenen Artikel ausführlicher behandelt haben: Idempotenz. Kurz gesagt beschreibt sie die Eigenschaft, dass es keinen Unterschied macht, ob ein Vorgang einmal oder fünfmal ausgeführt wird. Eine Statusänderung auf "bezahlt" ist idempotent, egal wie oft man sie setzt, das Ergebnis bleibt gleich. Eine Zahlung auslösen ist es nicht. Eine Mail verschicken ist es nicht. Einen Datensatz anlegen ist es nur dann, wenn man vorher prüft, ob er schon existiert.
Die unbequeme Wahrheit: Retries sind nur dann sicher, wenn die Aktion dahinter idempotent ist. Und die meisten interessanten Aktionen in einer Geschäftsautomatisierung sind es von Natur aus nicht. Man muss sie erst dazu machen.
Die drei Sorten von Fehlern
Bevor man über Wiederholungen nachdenkt, lohnt es sich, Fehler in drei Kategorien zu sortieren. Die Kategorie entscheidet über die richtige Reaktion, und sie zu verwechseln ist die häufigste Ursache für schlechte Retry-Logik.
Die erste Kategorie sind eindeutig vorübergehende Fehler. Ein HTTP-Statuscode 503, weil ein Server gerade neu startet. Ein Verbindungsabbruch mitten in der Übertragung. Ein Rate-Limit mit dem Status 429 und einem klaren Hinweis, wann man es wieder versuchen darf. Hier ist ein Retry die passende Antwort, sofern man ihn richtig baut.
Die zweite Kategorie sind eindeutig permanente Fehler. Der Statuscode 400, weil die Daten nicht ins Format passen. Ein 401, weil das Token abgelaufen ist. Ein 404, weil der Datensatz, den man aktualisieren will, gelöscht wurde. Diese Fehler durch Wiederholung lösen zu wollen, ist reine Verschwendung. Sie brauchen einen Menschen oder eine andere Logik, nie einfach denselben Versuch noch einmal.
Die dritte Kategorie ist die gefährlichste, und über sie redet kaum jemand: die mehrdeutigen Fehler. Ein Timeout gehört dazu. Ein abgebrochener Verbindungsaufbau nach dem Senden der Anfrage. Alles, wo man am Ende schlicht nicht weiß, ob die andere Seite den Auftrag ausgeführt hat oder nicht. Der Onlinehändler ist an dieser dritten Kategorie gescheitert. Ein Timeout heißt nicht "es ist nichts passiert". Ein Timeout heißt "ich weiß nicht, was passiert ist". Das ist ein gewaltiger Unterschied, und die meisten Plattformen behandeln beides gleich.
Wer seine Automatisierung ernst nimmt, behandelt diese drei Kategorien unterschiedlich. Vorübergehende Fehler wiederholt man. Permanente Fehler leitet man weiter. Mehrdeutige Fehler wiederholt man nur, wenn die Aktion idempotent ist, und sonst hält man an und fragt nach.
Warum naive Wiederholungen Ausfälle verstärken
Angenommen, ein von Ihnen genutzter Dienst hat ein Problem und antwortet bei jeder zweiten Anfrage mit einem Fehler. Ihre Automatisierung reagiert mit sofortiger Wiederholung. Was passiert?
Sie verdoppeln die Last auf einen Dienst, der ohnehin schon schwächelt. Statt ihm Luft zum Erholen zu geben, drücken Sie ihn tiefer. Wenn hundert Kunden dasselbe Tool nutzen und alle hundert Automatisierungen gleichzeitig auf sofortige Wiederholung stehen, dann trifft den angeschlagenen Dienst im Fehlermoment die doppelte, dreifache, vierfache Anfragemenge. In der Systemtechnik heißt dieses Muster Thundering Herd, die donnernde Herde. Ein kurzer Schluckauf wird zum vollen Ausfall, weil alle gleichzeitig nachdrücken.
Das Fatale ist die Rückkopplung. Der Dienst wird langsamer, dadurch laufen mehr Anfragen in den Timeout, dadurch werden mehr Wiederholungen ausgelöst, dadurch wird der Dienst noch langsamer. Ein System, das sich selbst tiefer in den Ausfall treibt, obwohl jede einzelne Komponente nur "vernünftig" reagiert. Genau deshalb sind naive Retries kein neutrales Sicherheitsnetz. Sie sind ein aktiver Beschleuniger im ungünstigsten Moment.
Und dann ist da noch die Kostenseite, die man in No-Code-Plattformen schnell übersieht. Jeder Wiederholungsversuch verbraucht eine Operation, einen Task, einen Ausführungsschritt, je nachdem wie der Anbieter abrechnet. Eine Automatisierung, die im Normalbetrieb 10.000 Schritte im Monat braucht, kann in einem einzigen schlechten Nachmittag mit endlosen Wiederholungen ihr gesamtes Monatskontingent verbrennen. Danach steht sie still, und zwar ausgerechnet der Teil, der eigentlich funktioniert.
Backoff und Jitter: die zwei Stellschrauben, die alles ändern
Es gibt zwei Techniken, die aus einem gefährlichen Retry einen brauchbaren machen. Beide sind seit Jahrzehnten Standard in der professionellen Softwareentwicklung, und beide fehlen in den meisten No-Code-Workflows, die wir zu sehen bekommen.
Die erste heißt Exponential Backoff, auf Deutsch etwa exponentiell wachsender Warteabstand. Statt sofort und immer im selben Takt zu wiederholen, verlängert man die Pause nach jedem Fehlversuch. Erster Versuch scheitert, eine Sekunde warten. Wieder gescheitert, zwei Sekunden. Dann vier, dann acht, dann sechzehn. Der Dienst bekommt mit jedem Schritt mehr Zeit, sich zu erholen, und Ihre Automatisierung hört auf, im Sekundentakt gegen eine geschlossene Tür zu rennen.
Die zweite Technik heißt Jitter, ein bewusst zufälliger Anteil in der Wartezeit. Der Grund ist die donnernde Herde von eben. Wenn alle Automatisierungen exakt gleich lang warten, dann schlagen sie nach der Pause auch wieder exakt gleichzeitig auf. Man hat das Problem nur um ein paar Sekunden verschoben. Mit Jitter wartet die eine Automatisierung 4,2 Sekunden, die nächste 5,8, die dritte 3,1. Die Herde verteilt sich, und der erholte Dienst wird nicht sofort wieder überrannt. Ein kleiner Zufallswert, große Wirkung.
In der Praxis kombiniert man beides: exponentiell wachsende Wartezeit plus ein zufälliger Aufschlag. In selbst gebautem Code sind das drei Zeilen. In n8n lässt sich das über die Retry-Einstellungen eines Nodes plus einen Wait-Node mit zufälliger Komponente nachbauen. In Make und Zapier ist es umständlicher, dort greift man oft zu einem Umweg über eine Fehlerbehandlungsroute mit gestaffelten Pausen. Umständlich, aber machbar, und der Unterschied im Ernstfall ist erheblich.
Der Circuit Breaker: irgendwann muss Schluss sein
Backoff macht Wiederholungen höflicher. Aber selbst höfliche Wiederholungen sind sinnlos, wenn der Dienst am anderen Ende komplett tot ist. Wenn ein Zielsystem seit zehn Minuten nicht antwortet, dann wird der 47. Versuch mit exponentiellem Backoff auch nichts ändern, außer weiter Kontingent zu verbrennen und die Fehlerlisten zu füllen.
Hier kommt ein Muster ins Spiel, das aus der Elektrotechnik geborgt ist: der Circuit Breaker, die Sicherung. Die Idee ist, dass ein System nach einer bestimmten Zahl von Fehlern in Folge aufhört, es überhaupt weiter zu versuchen. Die Sicherung fliegt raus. Für eine festgelegte Zeit werden keine neuen Anfragen an den kaputten Dienst geschickt, sie werden stattdessen sofort abgelehnt oder zur Seite gelegt. Nach der Wartezeit lässt der Circuit Breaker einen einzelnen Testversuch durch. Klappt er, geht der normale Betrieb weiter. Klappt er nicht, bleibt die Sicherung draußen.
Der Gewinn ist doppelt. Sie schonen den angeschlagenen Dienst, weil Sie ihn nicht mit sinnlosen Anfragen bombardieren, während er versucht, wieder hochzukommen. Und Sie schonen sich selbst, weil Sie nicht Tausende von Fehl-Ausführungen produzieren, die Sie hinterher aufräumen müssen.
In reinen No-Code-Umgebungen gibt es selten einen fertigen Circuit Breaker. Man baut ihn behelfsmäßig nach, etwa über eine zentrale Variable oder einen kleinen Datensatz, der zählt, wie viele Fehler in Folge aufgetreten sind, und der ab einer Schwelle einen Schalter umlegt, den die Automatisierung am Anfang prüft. Das ist Handarbeit. Aber ab einer gewissen Kritikalität eines Workflows ist es die Arbeit wert, und wir bauen genau das regelmäßig für Kunden, deren Prozesse an fragilen Fremdschnittstellen hängen.
Was passiert mit dem, was endgültig nicht durchgeht?
Irgendwann ist jede Wiederholung erschöpft. Der Backoff ist ausgereizt, die Sicherung ist geflogen, und trotzdem hängt da ein Vorgang, der einfach nicht durchgeht. Die entscheidende Frage lautet dann: Was passiert mit diesem Vorgang?
Die schlechteste Antwort ist: nichts. Der Vorgang verschwindet, die Fehlermeldung landet in einem Log, das niemand liest, und der betroffene Datensatz bleibt in einem halbfertigen Zustand zurück. Eine Bestellung ohne Bestätigung. Eine Zahlung ohne Buchung. Ein Lead, der nie im CRM ankam. Diese stillen Verluste sind schlimmer als ein lauter Ausfall, weil niemand sie bemerkt, bis sich Wochen später jemand beschwert.
Die bessere Antwort trägt in der Fachsprache den Namen Dead Letter Queue, der Briefkasten für unzustellbare Post. Alles, was nach allen Wiederholungen endgültig scheitert, wird nicht verworfen, sondern in einer separaten Liste gesammelt. Ein Fehlerprotokoll mit allem, was man zum Nachvollziehen braucht: welcher Datensatz, welche Aktion, welche Fehlermeldung, welcher Zeitpunkt. Ein Mensch schaut regelmäßig hinein, entscheidet, was zu tun ist, und stößt die Aktion nach der Behebung erneut an.
In der No-Code-Welt ist diese tote Briefkasten-Liste oft nichts Komplizierteres als eine eigene Tabelle, in die die Fehlerbehandlungsroute jeden endgültig gescheiterten Vorgang schreibt. Wichtig ist nur, dass es sie überhaupt gibt und dass jemand die Verantwortung hat, hineinzuschauen. Eine Automatisierung ohne diesen Auffangmechanismus verliert im Fehlerfall Daten, und meistens merkt man es erst, wenn es zu spät ist.
Ein verwandtes Konzept ist die vergiftete Nachricht, im Original poison message. Gemeint ist ein einzelner Datensatz, der jeden Verarbeitungsversuch zum Absturz bringt, etwa weil ein Feld einen Wert enthält, mit dem der Workflow nicht umgehen kann. Ohne Vorkehrung bleibt so ein Datensatz ewig ganz vorne in der Schlange, wird immer wieder verarbeitet, scheitert immer wieder, und blockiert dabei alles, was dahinter wartet. Ein Zähler, der nach der dritten oder vierten erfolglosen Runde denselben Datensatz aussortiert und in die tote Briefkasten-Liste schiebt, verhindert genau diese Blockade.
Was die Plattformen wirklich tun, und wo ihre Voreinstellungen gefährlich sind
Reden wir konkret. Denn die Theorie ist eine Sache, aber die Standardeinstellungen der Werkzeuge sind das, was am Ende im Ernstfall greift.
Zapier wiederholt fehlgeschlagene Schritte automatisch über einen gewissen Zeitraum, und das oft ohne dass der Ersteller es bewusst konfiguriert hat. Das ist bequem und für viele einfache Fälle in Ordnung. Gefährlich wird es genau dann, wenn der wiederholte Schritt nicht idempotent ist, also etwas verschickt oder auslöst. Dann bekommt man die Duplikate, die wir am Anfang beschrieben haben. Wer bei Zapier einen Schritt hat, der eine Mail sendet, eine Zahlung anstößt oder einen Datensatz anlegt, muss aktiv dafür sorgen, dass eine Wiederholung nicht doppelt wirkt.
Make bietet in den Szenario-Einstellungen die Wahl zwischen sofortigem Fehlerabbruch und einer Wiederholungslogik über die eingebauten Error-Handler. Das ist mächtiger als bei Zapier, verlangt aber auch mehr Wissen. Wir sehen oft Szenarien, in denen der Standard-Error-Handler fehlt und ein einzelner Fehler das ganze Szenario stoppt, oder umgekehrt Szenarien, die im Fehlerfall stur weiterlaufen und dabei halbe Datensätze produzieren. Der Rollback-Handler von Make ist ein nützliches Werkzeug, aber er wirkt nur auf die eingebauten Datenbank-Operationen, nicht auf die Nebenwirkungen bei externen Diensten. Eine bereits verschickte Mail holt kein Rollback zurück.
n8n gibt am meisten Kontrolle. Pro Node lassen sich Wiederholungen, Wartezeiten und Fehlerpfade konfigurieren, und über den Error-Trigger baut man eine zentrale Fehlerbehandlung für den ganzen Workflow. Das ist die gute Nachricht. Die schlechte: Genau weil man so viel selbst bestimmt, bestimmt man auch die Fehler selbst. Ein n8n-Workflow ohne durchdachte Retry- und Fehlerstrategie ist genauso verletzlich wie jeder andere, nur mit mehr Knöpfen, an denen man sich vergreifen kann.
Die gemeinsame Lehre über alle drei Plattformen: Die Voreinstellung ist selten die richtige. Sie ist auf den bequemen Normalfall optimiert, nicht auf den Tag, an dem eine Schnittstelle langsam wird. Und der Tag kommt.
Der mehrdeutige Fall im Detail
Zurück zur gefährlichsten Fehlerklasse, dem Timeout, weil sie in der Praxis den größten Schaden anrichtet und am wenigsten verstanden wird.
Stellen Sie sich vor, Ihre Automatisierung schickt eine Zahlungsanweisung an einen Zahlungsdienstleister. Die Anfrage geht raus, der Dienstleister verarbeitet sie, aber bevor seine Bestätigung bei Ihnen ankommt, reißt die Verbindung ab. Ihre Automatisierung sieht einen Timeout. Was jetzt?
Wiederholen Sie blind, riskieren Sie eine doppelte Zahlung. Wiederholen Sie nicht, riskieren Sie eine Zahlung, die vielleicht nie ausgeführt wurde. Beide Optionen können teuer werden, und Sie haben zu diesem Zeitpunkt schlicht keine Information darüber, welcher der beiden Fälle vorliegt.
Der saubere Ausweg heißt Idempotenzschlüssel. Sie schicken bei der ersten Anfrage einen eindeutigen Schlüssel mit, sagen wir eine ID, die diese eine Zahlung eindeutig kennzeichnet. Wiederholen Sie nach dem Timeout, schicken Sie denselben Schlüssel erneut mit. Der Zahlungsdienstleister erkennt: Diesen Schlüssel habe ich schon gesehen, die Zahlung ist bereits ausgeführt, ich gebe dir einfach das Ergebnis von damals zurück, ohne ein zweites Mal abzubuchen. Genau dafür bieten seriöse Zahlungsdienstleister diesen Mechanismus an, und wer mit Geld automatisiert, ohne ihn zu nutzen, spielt mit dem Feuer.
Für Aktionen ohne solchen eingebauten Schlüssel bleibt die Alternative: erst prüfen, dann handeln. Vor dem Wiederholen fragt die Automatisierung nach, ob der Vorgang vielleicht doch schon durchgelaufen ist. Existiert die Buchung bereits? Wurde die Mail als versendet markiert? Ist der Datensatz schon da? Erst wenn die Antwort nein lautet, wird wiederholt. Dieses zusätzliche Nachfragen kostet einen Schritt und ein paar Sekunden, aber es ist der Unterschied zwischen einer robusten und einer riskanten Automatisierung.
Eine praktische Reihenfolge für den Aufbau
Wenn wir mit einem Kunden eine belastbare Retry-Strategie aufsetzen, gehen wir eine feste Reihenfolge durch. Sie ersetzt kein Nachdenken über den konkreten Fall, aber sie sorgt dafür, dass die wichtigen Fragen gestellt werden.
Zuerst klären wir, ob die Aktion überhaupt gefahrlos wiederholbar ist. Wenn nein, kommt vor jeden Retry entweder ein Idempotenzschlüssel oder eine Prüfung. Ohne diesen Schritt bauen wir keine automatische Wiederholung ein, egal wie verlockend der Haken in den Einstellungen aussieht.
Dann trennen wir die Fehlerarten. Vorübergehende Fehler dürfen wiederholt werden, permanente werden sofort zur Seite gelegt und gemeldet, mehrdeutige werden wie beschrieben mit besonderer Vorsicht behandelt. Diese Unterscheidung landet direkt in der Verzweigungslogik des Workflows.
Danach legen wir Grenzen fest. Wie oft wird höchstens wiederholt? Mit welchem wachsenden Abstand? Ab wann fliegt die Sicherung? Es gibt keine für alle richtige Zahl, aber es gibt eine falsche: unendlich. Jede Wiederholung braucht eine Obergrenze, sonst wird aus dem Sicherheitsnetz irgendwann die Falle.
Zum Schluss bauen wir den Auffangmechanismus. Alles, was endgültig scheitert, geht in eine tote Briefkasten-Liste, die ein Mensch regelmäßig prüft. Und wir sorgen dafür, dass diese Liste sichtbar ist, nicht in einem Log versteckt, das niemand öffnet. Eine Fehlerbehandlung, die niemand sieht, ist keine Fehlerbehandlung.
Was wir Kunden am Ende sagen
Retries sind kein Schalter, den man aus Bequemlichkeit anlässt. Sie sind eine Designentscheidung mit Konsequenzen, und die schwerste davon zeigt sich erst am schlechten Tag, wenn eine Schnittstelle langsam wird und Ihre Automatisierung entscheiden muss, was sie damit anfängt.
Die gute Nachricht: Man braucht keine Doktorarbeit in verteilten Systemen, um es richtig zu machen. Es reicht, die richtigen Fragen zu stellen. Ist die Aktion gefahrlos wiederholbar? Welche Art von Fehler liegt vor? Wie oft wird höchstens versucht, und mit welchem Abstand? Wohin geht, was endgültig scheitert? Wer schaut da rein? Vier, fünf Fragen, die den Unterschied ausmachen zwischen einer Automatisierung, die Fehler abfedert, und einer, die sie verstärkt.
Der Onlinehändler mit den 40.000 Mails hat übrigens am selben Abend eine Prüfung vor den Mailversand gesetzt und den blinden Retry durch eine gestaffelte Wiederholung mit Obergrenze ersetzt. Seitdem ist es nicht wieder passiert. Die Reparatur hat zwei Stunden gedauert. Das Nachdenken davor hätte zehn Minuten gebraucht. So ist das mit Retries fast immer.