Retries, Duplikate und Idempotenz

23. Juli 2026 · 4 Min. Lesezeit

Webhook-Zustellung ist „mindestens einmal“, nie „genau einmal“. Das ist kein Bug – es ist die einzige ehrliche Garantie, die ein Netzwerk geben kann. Heißt: Irgendwann kommt dasselbe Ereignis zweimal, und dein Code muss darauf vorbereitet sein.

Warum dasselbe Ereignis zweimal ankommt

Der Anbieter sendet, dein Server verarbeitet die Bestellung und antwortet 200 – aber die Antwort geht auf dem Rückweg verloren. Aus Sicht des Anbieters ist die Zustellung gescheitert, also versucht er es erneut. Deine Seite verarbeitet dieselbe Bestellung ein zweites Mal. Niemand hat etwas falsch gemacht; das Netzwerk kann schlicht nicht mehr versprechen.

Wie Anbieter erneut zustellen

Typischerweise mit exponentiellem Backoff: nach Sekunden, dann Minuten, dann Stunden – Stripe versucht es bis zu drei Tage lang, GitHub gibt deutlich früher auf, und viele Anbieter deaktivieren einen Endpoint, der lange genug scheitert. Daraus folgt zweierlei: Ein kurzer Ausfall auf deiner Seite ist meist harmlos, und ein dauerhaft kaputter Endpoint bekommt irgendwann stillschweigend gar nichts mehr.

Das Idempotenz-Muster

Idempotent heißt: Dasselbe Ereignis zweimal zu verarbeiten hat denselben Effekt wie einmal. Das Rezept ist immer dasselbe – Ereignis-ID aus dem Payload nehmen, merken, Bekanntes überspringen:

async function handleWebhook(event) {
  const id = event.id;                  // eindeutige Ereignis-ID des Anbieters
  if (await seen.has(id)) return 200;   // schon verarbeitet → fertig
  await seen.add(id, { ttl: "7d" });    // merken, bevor gearbeitet wird
  await doTheWork(event);               // abbuchen, mailen, freischalten …
  return 200;
}

Speichere die IDs dort, wo du ohnehin Zustand hältst – eine Datenbanktabelle mit Unique-Index, Redis mit TTL. Der Unique-Index ist der wichtige Teil: Er macht die Prüfung atomar, sodass zwei gleichzeitige Zustellungen nicht beide durchkommen.

Und wenn es keine Ereignis-ID gibt?

Bau dir eine aus stabilen Feldern: order_id + event_type + timestamp, gehasht. Alles, was das Ereignis identifiziert und sich zwischen Retries nicht ändert, funktioniert.

Schnell antworten, später arbeiten

Die wirksamste Maßnahme gegen Retries ist ein schnelles 2xx. Validieren, Job in eine Queue legen, sofort antworten – dann die langsame Arbeit erledigen. Ein Webhook-Handler, der E-Mails synchron verschickt, läuft irgendwann in einen Timeout, wird erneut zugestellt und verschickt die Mail zweimal.

Wann Duplikate egal sind

Sei pragmatisch: Löst der Webhook nur eine Push-Benachrichtigung aus, bedeutet ein Duplikat, dass du einen Ton doppelt hörst – lästig, nicht teuer. Der Aufwand sollte zu den Konsequenzen passen: volle Idempotenz bei Zahlungen und Freischaltungen, entspannt bei reinen Benachrichtigungen.

Mehr: Welchen Statuscode zurückgeben? · Best Practices

Hol dir Webhooky

Kostenlos für deine ersten 100 Benachrichtigungen – Endpoint in zwei Minuten eingerichtet.

Jetzt bei Google Play Laden im App Store