Zum Inhalt springen
SAP, DATEV und Dynamics Experten
Alle Artikel Middleware

Idempotenz und Retry-Strategien für robuste Schnittstellen

13 Min. Lesezeit
IdempotenzRetryMiddleware

In verteilten Systemen ist die unbequeme Wahrheit: Eine Antwort, die nicht ankommt, ist nicht dasselbe wie eine Aktion, die nicht ausgeführt wurde. Wenn ein Bestell-Sync zwischen Shop und ERP nach einem Timeout abbricht, weiß die Middleware zunächst nicht, ob die Bestellung im ERP angelegt wurde oder nicht. Wiederholt sie den Aufruf blind, riskiert sie eine doppelte Bestellung. Wiederholt sie ihn nicht, riskiert sie eine verlorene Bestellung. Laut der AWS Builders Library lassen sich die meisten dieser Fehler sicher wiederholen, wenn die Schnittstelle zwei Eigenschaften besitzt: Idempotenz auf der Empfängerseite und eine intelligente Retry-Strategie auf der Senderseite (AWS Builders Library, 2024). Dieser Artikel zeigt, wie Idempotency-Keys, Exponential Backoff mit Jitter, Deduplizierung und Dead-Letter-Queues zusammenwirken, um Bestell- und Bestands-Syncs gefahrlos wiederholbar zu machen -- und wie eine Shop-Integration diese Mechanismen in der Praxis umsetzt.

Idempotenz und Retry-StrategienShopBestellung + KeyIdempotency-StoreKey bekannt?Dedup-PrüfungRetry-EngineBackoff + Jittermax 5 VersucheERP / SAPZielsystemSichere Wiederholung mit Exponential BackoffVersuch 1nach 1sVersuch 2nach 2s + JitterVersuch 3nach 4s + JitterVersuch 4nach 8s + JitterVersuch 5nach 16s + JitterErfolg: Key als verarbeitet markiertspätere Duplikate werden ignoriertDead-Letter-Queuenach max. Versuchenmanuelle KlärungAt-least-once ZustellungJede Nachricht kommt mindestens einmal an,möglicherweise mehrfach. Duplikate sinderlaubt und werden vom Empfänger entfernt.Idempotenz macht den Empfängerunempfindlich gegen Wiederholungen.Deduplizierung im StoreIdempotency-Key wird gespeichert, bevorder Auftrag ans ERP geht. Trifft derselbeKey erneut ein, wird das Ergebnis desersten Aufrufs zurückgegeben.Keine doppelten Bestellungen im ERP.

Warum jede Schnittstelle mit Wiederholungen rechnen muss

Zwischen Shop und ERP liegen Netzwerke, Lastverteiler, Warteschlangen und mehrere Anwendungen. Jede dieser Stationen kann eine Anfrage verzögern, abbrechen oder eine Antwort verschlucken. Das Google SRE Book formuliert es als Grundannahme: In einem ausreichend großen System tritt jeder mögliche Fehler irgendwann tatsächlich auf (Google SRE Book, 2017). Für eine Bestell-Schnittstelle bedeutet das konkret: Es ist keine Frage, ob ein Aufruf einmal hängenbleibt, sondern wie oft und wie die Integration darauf reagiert.

Das Kernproblem ist die Mehrdeutigkeit eines Timeouts. Sendet die API-Schicht eine Bestellung an das ERP und erhält keine Antwort, gibt es drei mögliche Realitäten: Die Anfrage erreichte das ERP nie, sie wurde verarbeitet aber die Antwort ging verloren, oder sie wird gerade noch verarbeitet. Aus Sicht des Senders sehen alle drei Fälle identisch aus. Eine naive Wiederholung behandelt sie gleich -- mit potenziell fatalen Folgen, wenn die Bestellung tatsächlich schon angelegt wurde.

Laut der AWS Builders Library sind 76 Prozent (AWS Builders Library, 2024) der Fehler in serviceorientierten Architekturen temporärer Natur -- Drosselung, kurzzeitige Überlast, Netzwerk-Jitter. Genau diese Fehler verschwinden bei einer Wiederholung. Die Aufgabe besteht also nicht darin, Wiederholungen zu vermeiden, sondern sie so zu gestalten, dass sie keinen Schaden anrichten. Genau hier setzen Idempotenz und durchdachte Retry-Strategien an, die wir in jedem Integrationsprojekt als Standard verankern.

At-least-once vs. exactly-once: die ehrliche Antwort

Viele Lastenhefte fordern eine 'exactly-once'-Zustellung: Jede Bestellung soll genau einmal verarbeitet werden, nie verloren, nie doppelt. In der Praxis ist eine echte exactly-once-Zustellung über Systemgrenzen hinweg jedoch außerordentlich schwer und teuer zu erreichen, weil Sender und Empfänger sich über jeden einzelnen Verarbeitungsschritt verteilt einigen müssten. Die ehrlichere und robustere Antwort ist eine Kombination: At-least-once-Zustellung plus idempotente Verarbeitung ergeben in der Wirkung ein 'effectively-once'-Verhalten.

EigenschaftAt-least-onceExactly-once (idealisiert)
ZustellgarantieMindestens einmal, Duplikate möglichGenau einmal, keine Duplikate
ImplementierungsaufwandModerat, gut beherrschbarHoch, oft nur theoretisch sauber
Verhalten bei TimeoutSicher wiederholbarSchwer sicherzustellen
Voraussetzung beim EmpfängerIdempotenz / DeduplizierungVerteilte Transaktion / Koordination
Praxis-EmpfehlungStandard für Shop-ERP-SyncsSelten nötig, hohe Kosten

Der Grund für diese Empfehlung ist pragmatisch: At-least-once ist mit Warteschlangen und Wiederholungen einfach umzusetzen, und Duplikate sind ein lösbares Problem -- man entfernt sie auf der Empfängerseite über einen Idempotency-Key. Bei Event-Streaming-Plattformen ist exactly-once-Semantik nur innerhalb eines kontrollierten Systems erreichbar, während über externe Systemgrenzen hinweg in der Regel auf idempotente Empfänger gesetzt wird (Projekterfahrung). Für die Anbindung an SAP oder ein anderes ERP heißt das: Wir setzen nicht voraus, dass eine Nachricht nie zweimal ankommt -- wir sorgen dafür, dass eine doppelt ankommende Nachricht folgenlos bleibt.

Die zentrale Faustregel

Mache den Transport unzuverlässig-aber-hartnäckig (at-least-once) und den Empfänger duplikat-resistent (idempotent). Diese Kombination ist einfacher, billiger und in der Praxis zuverlässiger als der Versuch, einen perfekten exactly-once-Transport zu bauen.

Idempotency-Keys: der Schlüssel zur sicheren Wiederholung

Eine Operation ist idempotent, wenn ihre mehrfache Ausführung denselben Effekt hat wie eine einmalige Ausführung. Das Anlegen einer Bestellung ist von Natur aus nicht idempotent -- ohne Schutz entstehen bei jedem Aufruf neue Datensätze. Der Idempotency-Key macht die Operation idempotent: Der Sender erzeugt für jede logische Operation einen eindeutigen Schlüssel und sendet ihn mit jedem Versuch unverändert mit. Der Empfänger speichert den Schlüssel zusammen mit dem Ergebnis und gibt bei einem zweiten Aufruf mit demselben Schlüssel einfach das gespeicherte Ergebnis zurück, ohne die Operation erneut auszuführen.

Stripe hat dieses Muster für Zahlungs-APIs prominent dokumentiert: Ein per Header übergebener Idempotency-Key stellt sicher, dass ein durch Netzwerkfehler wiederholter Aufruf nicht zu einer zweiten Abbuchung führt (Stripe Engineering, 2024). Dasselbe Prinzip schützt eine Bestell-Schnittstelle vor doppelten Aufträgen. Entscheidend ist, dass der Schlüssel auf der Senderseite einmal erzeugt und über alle Wiederholungen hinweg stabil bleibt -- ein bei jedem Versuch neu generierter Schlüssel würde den Schutz aushebeln.

In der Middleware leiten wir den Schlüssel aus geschäftsrelevanten, stabilen Daten ab. Für Bestellungen eignet sich die Shopware-Bestellnummer in Kombination mit dem Vorgangstyp. Für Bestandsmeldungen die Kombination aus Artikelnummer und Quell-Zeitstempel. So bleibt derselbe fachliche Vorgang über beliebig viele technische Wiederholungen hinweg auf denselben Schlüssel abgebildet, während eine echte neue Bestellung zwangsläufig einen neuen Schlüssel erhält.

idempotenz-prüfung.js
// Vereinfachte Idempotenz-Prüfung in der Middleware
async function verarbeiteBestellung(bestellung) {
  const key = idempotencyKey(bestellung); // z.B. 'order:SW-100245'

  const bekannt = await store.holeErgebnis(key);
  if (bekannt) {
    // Schluessel bereits verarbeitet -> gespeichertes Ergebnis zurückgeben
    return bekannt.ergebnis; // keine zweite ERP-Anlage
  }

  // Key reservieren, bevor der ERP-Aufruf erfolgt
  await store.reserviere(key);
  const ergebnis = await erp.legeBestellungAn(bestellung);

  await store.speichereErgebnis(key, ergebnis, { ttlTage: 30 });
  return ergebnis;
}

Deduplizierung: Duplikate erkennen, bevor sie Schaden anrichten

Die Deduplizierung ist die Empfängerseite der Idempotenz-Medaille. Sie beantwortet die Frage: Habe ich diesen fachlichen Vorgang schon einmal gesehen? Dafür hält die Integrationsschicht einen persistenten Idempotency-Store -- eine Tabelle, die jeden verarbeiteten Schlüssel mit Status, Zeitstempel und Verarbeitungsergebnis festhält. Trifft ein bereits bekannter Schlüssel erneut ein, wird die Operation nicht ausgeführt, sondern als Duplikat verbucht und das ursprüngliche Ergebnis zurückgegeben.

Ein subtiler, aber wichtiger Punkt ist das Zeitfenster der Deduplizierung. Schlüssel müssen lange genug gespeichert werden, um realistische Wiederholungen abzudecken -- ein Sync, der nach Stunden aus einer Dead-Letter-Queue erneut versucht wird, muss noch als Duplikat erkannt werden. Gleichzeitig sollte der Store nicht unbegrenzt wachsen. In der Praxis hat sich eine Aufbewahrung der Schlüssel über mehrere Wochen bewährt, abgestimmt auf die maximale Lebensdauer einer Nachricht im System.

Eindeutiger Schlüssel

Aus stabilen Geschäftsdaten abgeleitet (Bestellnummer, Artikel plus Zeitstempel) -- über alle Wiederholungen hinweg identisch.

Persistenter Store

Jeder Schlüssel wird mit Status und Ergebnis gespeichert. Überlebt Neustarts, sodass auch verzögerte Wiederholungen erkannt werden.

Folgenloser Zweittreffer

Ein erneut eintreffender Schlüssel löst keine zweite Verarbeitung aus -- das ERP sieht den Auftrag nur einmal.

Aufbewahrungsfenster

Schlüssel bleiben lange genug erhalten, um späte Retries aus der Dead-Letter-Queue noch als Duplikat zu erkennen.

Status-Reservierung

Der Schlüssel wird reserviert, bevor der ERP-Aufruf startet -- parallele Versuche kollidieren nicht miteinander.

Audit-Verbindung

Jeder Schlüssel ist mit der Korrelations-ID verknüpft, sodass Duplikate im Audit-Log nachvollziehbar bleiben.

Wichtig ist die Reihenfolge: Der Schlüssel wird reserviert, bevor der eigentliche ERP-Aufruf erfolgt. Würde man ihn erst nach erfolgreicher Verarbeitung speichern, entstünde ein Zeitfenster, in dem zwei parallele Versuche beide den Auftrag anlegen. Die API-Schnittstelle nutzt daher eine zweistufige Buchung: erst Reservierung des Schlüssels mit Status 'in Arbeit', dann Aktualisierung auf 'abgeschlossen' samt Ergebnis. Trifft ein zweiter Versuch auf einen Schlüssel im Status 'in Arbeit', wartet er kurz und übernimmt anschließend das Ergebnis des ersten Versuchs.

Exponential Backoff mit Jitter: Wiederholungen entzerren

Wenn ein Aufruf fehlschlägt und sofort wiederholt wird, trifft er oft auf dasselbe Problem -- ein überlastetes System bleibt überlastet. Schlimmer noch: Wiederholen viele Sender gleichzeitig im selben Takt, entsteht ein synchronisierter Ansturm, der die Erholung verzögert. Exponential Backoff löst das erste Problem, indem die Wartezeit nach jedem Fehlversuch wächst (etwa 1, 2, 4, 8, 16 Sekunden). Jitter -- ein zufälliger Versatz auf die Wartezeit -- löst das zweite Problem, indem es die Wiederholungen über die Zeit verteilt.

Die AWS Builders Library hat dieses Zusammenspiel detailliert untersucht und empfiehlt ausdrücklich Backoff mit Jitter, weil reines exponentielles Backoff ohne Zufallskomponente weiterhin zu Lastspitzen führen kann (AWS Builders Library, 2024). Das Google SRE Book ergänzt, dass Retries grundsätzlich begrenzt und über die gesamte Aufrufkette budgetiert werden müssen, damit Wiederholungen nicht selbst eine Überlast erzeugen (Google SRE Book, 2017).

backoff-jitter.js
// Exponential Backoff mit Full Jitter
function wartezeitMs(versuch, basis = 1000, max = 30000) {
  const exp = Math.min(max, basis * 2 ** versuch);
  // Full Jitter: gleichverteilt zwischen 0 und exp
  return Math.floor(Math.random() * exp);
}

async function mitRetry(aktion, maxVersuche = 5) {
  for (let versuch = 0; versuch < maxVersuche; versuch++) {
    try {
      return await aktion();
    } catch (fehler) {
      if (!istTemporaer(fehler) || versuch === maxVersuche - 1) {
        throw fehler; // permanent oder Budget erschoepft -> DLQ
      }
      await schlafe(wartezeitMs(versuch));
    }
  }
}

Entscheidend ist die Unterscheidung zwischen temporären und permanenten Fehlern, bevor überhaupt wiederholt wird. Ein HTTP 429 (Drosselung) oder 503 (Dienst nicht verfügbar) ist ein klarer Kandidat für einen Retry -- idealerweise unter Beachtung eines vorhandenen 'Retry-After'-Headers. Ein HTTP 400 oder 422 (fachlicher Validierungsfehler) hingegen wird durch Wiederholung nicht besser und gehört direkt in die Klärung. Diese Klassifizierung beschreiben wir ausführlich im Schwesterartikel zur Fehlerbehandlung in Schnittstellen, der zeigt, wann Push- und wann Pull-basierte Übertragung sinnvoll ist.

Dead-Letter-Queues: das Sicherheitsnetz nach erschöpften Versuchen

Auch die beste Retry-Strategie endet irgendwann. Wenn ein Aufruf nach der maximalen Anzahl Versuche weiterhin scheitert oder von vornherein als permanent fehlerhaft erkannt wird, darf die Nachricht nicht einfach verworfen werden. Die Dead-Letter-Queue (DLQ) fängt genau diese Nachrichten auf. Sie speichert den vollständigen Vorgang mit Kontext: ursprünglicher Inhalt, Fehlergrund, Anzahl der Versuche, Zeitstempel und Korrelations-ID. So geht keine Bestellung und keine Bestandsmeldung verloren, selbst wenn das Zielsystem über längere Zeit gestört ist.

Die DLQ ist weit mehr als ein Mülleimer. Sie ist eine bewusst kuratierte Warteschlange für Fälle, die menschliche Aufmerksamkeit oder eine korrigierte Wiederholung benötigen. In jeder Integrationslösung wird sie über ein Dashboard zugänglich gemacht: Eine Fachkraft sieht jeden gestrandeten Vorgang, kann die Daten korrigieren und den Vorgang gezielt neu in die Verarbeitungspipeline einspeisen. Da die Wiederholung wieder denselben Idempotency-Key trägt, ist auch dieser späte Neuversuch gegen Duplikate geschützt.

  • Vollständiger Kontext: Jeder DLQ-Eintrag enthält Originalnachricht, Fehlerursache, Versuchszähler und Korrelations-ID für die lückenlose Nachverfolgung.
  • Kontrollierte Wiederaufnahme: Korrigierte Vorgänge werden mit unverändertem Idempotency-Key neu eingespeist -- die Deduplizierung verhindert weiterhin Duplikate.
  • Mustererkennung: Häufungen gleichartiger Einträge in der DLQ weisen auf systematische Probleme hin, etwa ein geändertes ERP-Datenmodell.
  • Alarmierung: Jeder neue DLQ-Eintrag oder ein schnelles Anwachsen der Queue löst eine Benachrichtigung an das Betriebsteam aus.
  • Aufbewahrung: DLQ-Einträge bleiben revisionssicher erhalten, bis sie geklärt sind -- nichts wird stillschweigend gelöscht.

Das Zusammenspiel aus begrenztem Retry und nachgelagerter DLQ erreicht in unseren Projekten eine Verarbeitungsquote von rund 99,9 Prozent (Projekterfahrung) für die temporär fehlgeschlagenen Vorgänge, während die wenigen verbleibenden Fälle sicher in der DLQ landen statt verloren zu gehen. Diese Architektur ist Standard in jeder Shop-ERP-Anbindung, die wir umsetzen.

Bestell-Sync sicher wiederholbar machen

Der Bestell-Sync ist der kritischste Datenfluss zwischen Shop und ERP, weil hier echtes Geld und echte Lieferungen im Spiel sind. Eine doppelt angelegte Bestellung führt zu doppelter Kommissionierung, doppelter Rechnung und verärgerten Kunden. Eine verlorene Bestellung führt zu ausbleibender Lieferung. Beide Fehler sind teuer. Die Kombination aus stabilem Idempotency-Key, at-least-once-Transport und idempotenter ERP-Anlage schließt beide Risiken: Eine Bestellung wird so oft wiederholt, bis sie sicher angekommen ist, aber niemals doppelt angelegt.

Praktisch heißt das: Die Integrationsschicht erzeugt beim Empfang der Bestellung den Schlüssel aus der Bestellnummer, persistiert die Nachricht in einer Warteschlange und versucht die ERP-Anlage. Schlägt der Aufruf temporär fehl, greift Backoff mit Jitter. Kommt während dieser Versuche eine identische Bestellnachricht erneut an -- etwa weil der Shop das Webhook erneut sendet -- erkennt die Deduplizierung den Schlüssel und verwirft das Duplikat. Erst wenn das ERP eine Auftragsnummer zurückmeldet, gilt der Vorgang als abgeschlossen und der Schlüssel wird final markiert.

Sales-Anschluss

Wir richten diese Bestell-Sync-Architektur als festen Bestandteil jeder Integration ein -- ohne Aufpreis als optionales Extra, sondern als selbstverständliche Grundqualität. Eine bestehende Anbindung, die heute noch ohne Idempotenz arbeitet, rüsten wir nach laufendem Betrieb auf, ohne den Shop offline zu nehmen.

Bestands-Sync: Wiederholungen ohne Geisterbestände

Beim Bestands-Sync lauert eine andere Falle. Bestandsänderungen werden oft als Deltas übertragen -- 'minus 3 Stück' statt 'neuer Stand: 17 Stück'. Ein wiederholtes Delta ist gefährlich: Wird 'minus 3' versehentlich zweimal verarbeitet, sinkt der Bestand um 6 statt um 3, und es entstehen Geisterbestände, die nicht der Realität entsprechen. Hier zeigt sich der Wert der Idempotenz besonders deutlich, denn Delta-Operationen sind von Natur aus nicht idempotent.

Zwei bewährte Ansätze entschärfen das Problem. Erstens: absolute statt relative Werte übertragen, wo möglich -- ein absoluter Sollbestand ('Stand: 17') ist von Natur aus idempotent, weil eine Wiederholung denselben Stand setzt. Zweitens: Wenn Deltas unvermeidbar sind, schützt ein Idempotency-Key pro Bewegung in Kombination mit der Deduplizierung vor doppelter Anwendung. Auch beim Einsatz einer Middleware bzw. iPaaS gilt für Synchronisationsmuster, dass idempotente Upsert-Operationen einer reinen Delta-Verarbeitung vorzuziehen sind, wenn die Übertragung unzuverlässig sein kann (Projekterfahrung).

Absolute Werte schlagen Deltas

Wann immer das ERP den absoluten Soll-Bestand liefern kann, übertragen wir diesen statt einer relativen Veränderung. Ein absoluter Bestand kann beliebig oft gesetzt werden, ohne den Wert zu verfälschen -- die einfachste Form von Idempotenz, ganz ohne zusätzlichen Schlüssel.

Beobachtbarkeit: Wiederholungen messbar machen

Eine Retry-Strategie, die niemand beobachtet, kann unbemerkt entgleisen. Wenn die Zahl der Wiederholungen still ansteigt, ist das ein Frühwarnzeichen für ein gestörtes Zielsystem -- lange bevor die ersten Vorgänge in der DLQ landen. Deshalb verknüpfen wir jeden Vorgang mit einer Korrelations-ID und protokollieren jeden Versuch strukturiert: Zeitpunkt, Fehlerklasse, Wartezeit, Versuchsnummer. So lässt sich der gesamte Weg einer Bestellung über alle Wiederholungen hinweg nachvollziehen.

Gartner weist darauf hin, dass mangelnde Beobachtbarkeit von Integrationsflüssen eine der häufigsten Ursachen für lange Fehlerbehebungszeiten ist und empfiehlt durchgängiges Monitoring der Schnittstellen-Gesundheit als festen Bestandteil moderner Integrationsplattformen (Gartner, 2024). Konkret überwachen wir die Retry-Rate je Zielsystem, die durchschnittliche Anzahl Versuche bis zum Erfolg, die Tiefe der Dead-Letter-Queue und die Trefferquote der Deduplizierung. Ein plötzlicher Anstieg der Duplikat-Treffer kann etwa darauf hinweisen, dass der Shop Webhooks mehrfach sendet -- ein Hinweis, der ohne Messung verborgen bliebe.

Hope is not a strategy. Verlasse dich nicht darauf, dass ein Aufruf ankommt -- baue Systeme, die mit dem Gegenteil rechnen und trotzdem korrekt bleiben.

Sinngemäß nach dem Google SRE Book (2017)

Nachrüstung in bestehenden Integrationen

Viele bestehende Schnittstellen wurden ohne Idempotenz gebaut und funktionieren im Normalbetrieb scheinbar problemlos -- bis der erste Netzwerkfehler eine doppelte Bestellung erzeugt. Die gute Nachricht: Idempotenz und Retry-Strategien lassen sich in laufende Shop-Integrationen nachrüsten, ohne den Betrieb zu unterbrechen. Wir gehen dabei in klar abgegrenzten Schritten vor, die jeweils einen messbaren Resilienz-Gewinn bringen.

  1. Analyse (rund 1 Woche): Bestehende Datenflüsse kartieren, nicht-idempotente Operationen identifizieren, Schlüsselableitung pro Vorgangstyp festlegen.
  2. Idempotency-Store einführen (1--2 Wochen): Persistente Schlüsseltabelle anlegen, zweistufige Reservierung implementieren, Deduplizierung in die Verarbeitung einhängen.
  3. Retry mit Backoff und Jitter (1 Woche): Fehlerklassifizierung ergänzen, Wartezeit-Strategie und Versuchsbudget konfigurieren, 'Retry-After' respektieren.
  4. Dead-Letter-Queue (1 Woche): DLQ mit vollständigem Kontext aufsetzen, Dashboard und Wiederaufnahme bereitstellen, Alarmierung anbinden.
  5. Beobachtbarkeit und Test (1 Woche): Korrelations-IDs durchziehen, Retry-Metriken instrumentieren, Fehlerinjektion zum Verifizieren der Wiederholbarkeit durchführen.

Über 50+ (Projekterfahrung) umgesetzte Integrationsprojekte hinweg hat sich gezeigt, dass die Nachrüstung der Idempotenz typischerweise innerhalb weniger Wochen erfolgt und sich durch entfallende manuelle Korrekturen schnell bezahlt macht. Wenn Sie wissen möchten, wie sich Ihre konkrete Shop-ERP-Anbindung absichern lässt, sprechen wir gern über Ihren individuellen Aufwand.

Dieser Artikel basiert auf Daten aus: AWS Builders Library (2024), Google SRE Book (2017), Stripe Engineering (2024), Gartner Integration Best Practices (2024) und eigener Projekterfahrung.