Ein Klassiker im Alltag: Ein Nutzer klickt zweimal auf âKaufenâ, die App hĂ€ngt kurz, ein Load-Balancer wiederholt Requests, oder ein Client fĂŒhrt automatisch Retries aus. Ohne Schutz kann daraus schnell eine doppelte Bestellung werden. Genau hier helfen Idempotency Keys: Sie sorgen dafĂŒr, dass ein API-Aufruf mit denselben Eingaben nur einmal âzĂ€hltâ, auch wenn er technisch mehrfach gesendet wird.
Warum doppelte Requests ĂŒberhaupt entstehen
Viele Duplikate sind keine âFehlerâ, sondern normale Effekte verteilter Systeme. Besonders hĂ€ufig passiert das bei VorgĂ€ngen, die Geld, Kontingente oder Buchungen betreffen.
Typische Auslöser im Web und Mobile
- Retries des Clients nach Timeout (z. B. Mobilfunkwechsel oder kurze Netzunterbrechung)
- Browser sendet ein Formular erneut (Reload, Back/Forward, Auto-Fill-Workflows)
- Der Nutzer klickt mehrfach, weil keine schnelle RĂŒckmeldung kommt
- Reverse Proxy / Gateway bricht Verbindungen ab, obwohl der Backend-Request weiterlÀuft
- Queues oder Worker starten Jobs erneut nach AbstĂŒrzen
Wichtig: Selbst wenn ein Request im Client âfehlgeschlagenâ wirkt, kann er im Server erfolgreich gewesen sein. Genau diese Unsicherheit fĂŒhrt zu doppelten AusfĂŒhrungen.
Idempotent vs. âeinmaligâ: ein kurzer BegriffsklĂ€rer
âIdempotentâ bedeutet: Derselbe Aufruf kann mehrfach passieren, das Ergebnis bleibt gleich. Bei HTTP ist das fĂŒr GET (lesen) grundsĂ€tzlich gegeben. Bei POST (anlegen/ausfĂŒhren) ist es das meist nicht, weil jeder POST eine neue Aktion auslösen kann. Idempotency ist deshalb ein Zusatzkonzept, das sichere Wiederholungen fĂŒr kritische POST/PUT-Ă€hnliche Aktionen ermöglicht.
Wie Idempotency Keys funktionieren (Prinzip)
Die Idee ist einfach: Der Client sendet zu einem Request eine eindeutige Kennung mit. Der Server merkt sich, dass diese Kennung bereits verarbeitet wurde, und liefert bei Wiederholung nicht ânochmal ausfĂŒhrenâ, sondern âgleiches Ergebnis wie beim ersten Malâ.
Das Grundmuster in 3 Schritten
- Client erzeugt einen zufÀlligen, eindeutigen Key (z. B. UUID) pro Aktion.
- Client sendet den Key in einem Header, z. B. Idempotency-Key.
- Server speichert Key + Ergebnis (oder Referenz) und gibt bei Duplikaten die gespeicherte Antwort zurĂŒck.
Damit wird aus einem âunsicheren POSTâ praktisch ein sicher wiederholbarer Vorgang, ohne dass der Client komplexe Logik bauen muss.
HTTP-Design: Header, Statuscodes und Antworten
In der Praxis ist ein klarer Vertrag entscheidend: Welche Requests dĂŒrfen einen Key nutzen? Wie lange ist er gĂŒltig? Was passiert, wenn Payload oder Nutzerkontext nicht passen?
Empfohlene Request-Form
Ein gÀngiges Muster sieht so aus:
- POST /orders
- Header: Idempotency-Key: <random>
- Body: die Bestelldaten
Der Key gehört pro âBusiness-Aktionâ genau einmal verwendet, nicht pro Retry. Retries sollen denselben Key wiederverwenden.
Welche Response sollte bei Duplikaten zurĂŒckkommen?
Viele APIs geben bei Wiederholung exakt denselben Body und Statuscode zurĂŒck wie beim ersten Durchlauf (z. B. 201 Created mit Order-ID). Das ist fĂŒr Clients am einfachsten zu handhaben.
Wichtig ist Konsistenz: Wenn ein Key bereits verarbeitet wurde, sollte der Server keinen neuen Datensatz erzeugen und auch keine neue Nebenwirkung auslösen.
Wenn zu demselben Key eine andere Payload geschickt wird, ist das ein echter Konflikt. Dann ist eine klare Fehlermeldung sinnvoll (oft 409 Conflict), damit der Client den Fehler sieht statt stillschweigend âfalscheâ Ergebnisse zu bekommen. Wenn Statuscodes im Team öfter diskutiert werden, hilft der Ăberblick aus HTTP Statuscodes verstehen â Fehler sauber behandeln.
Backend-Implementierung: so bleibt es wirklich sicher
Der schwerste Teil ist nicht der Header, sondern die korrekte Speicherung und Absicherung im Backend. Es reicht nicht, nur âKey gesehenâ zu speichern â es muss auch bei parallelen Requests funktionieren.
Speicherstrategie: was wird pro Key abgelegt?
Mindestens nötig:
- Idempotency-Key
- Scope (z. B. User-ID oder API-Key), damit Keys nicht zwischen Nutzern kollidieren
- Hash der Request-Payload (oder relevante Felder), um âgleicher Key, andere Datenâ zu erkennen
- Status (in Bearbeitung / abgeschlossen / fehlgeschlagen)
- Response-Daten oder eine Referenz (z. B. erzeugte Order-ID)
- Ablaufdatum (TTL), damit die Tabelle nicht ewig wÀchst
ParallelitÀt: Race Conditions verhindern
Wenn zwei identische Requests gleichzeitig eintreffen, mĂŒssen sie sich gegenseitig âsehenâ. Sonst erzeugen beide eine Bestellung, bevor einer den Key speichert. Das lĂ€sst sich stabil lösen, indem die Speicherung atomar (unteilbar) passiert, typischerweise ĂŒber einen Unique-Index in der Datenbank.
Praktisches Muster:
- Versuch, einen Datensatz (scope + key) anzulegen.
- Wenn erfolgreich: der Request âbesitztâ den Key und verarbeitet die Aktion.
- Wenn Unique-Verletzung: Key existiert schon â gespeichertes Ergebnis zurĂŒckgeben (oder warten, wenn noch âin Bearbeitungâ).
Bei lĂ€ngeren VorgĂ€ngen kann ein âin Bearbeitungâ-Status wichtig sein, damit ein zweiter Request nicht sofort scheitert, sondern das Ergebnis spĂ€ter abrufen kann (je nach API-Design).
Datenbank, Cache oder beides?
FĂŒr kritische Aktionen ist die Datenbank oft die robusteste Wahl, weil sie Konsistenz und Unique-Constraints zuverlĂ€ssig abbildet. Ein Cache (z. B. Redis) kann ergĂ€nzen, um fertige Antworten schnell auszuliefern, sollte aber nicht der einzige Ort sein, wenn Datenverlust inakzeptabel ist.
Ein kleines Fallbeispiel: Checkout mit unsicherem Netz
Eine Mobile-App sendet POST /payments. Nach 8 Sekunden Timeout zeigt die App âZahlung fehlgeschlagenâ und der Nutzer tippt erneut. Ohne Idempotency Key entstehen zwei Zahlungen. Mit Key passiert Folgendes:
- Erster Request startet, Server legt Key an und verarbeitet die Zahlung.
- App sendet erneut denselben Key (Retry oder erneuter Tap).
- Server erkennt den Key und liefert die erste Payment-ID zurĂŒck, statt erneut abzubuchen.
Das senkt nicht nur das Risiko von Doppelbuchungen, sondern reduziert auch Support-Aufwand und âunerkĂ€rlicheâ ZustĂ€nde im System.
Praxis-Box: robuste Umsetzung in kurzen Schritten
- Definiere, welche Endpoints einen Idempotency-Key akzeptieren (meist POST fĂŒr Create/Execute).
- Lege den Scope fest (mindestens pro Nutzer oder pro API-Client).
- Speichere Key + Payload-Hash + Ergebnisreferenz in einer Tabelle mit Unique-Constraint.
- Behandle parallele Requests sauber: Insert zuerst, dann ausfĂŒhren; bei Konflikt Ergebnis zurĂŒckgeben.
- Setze ein Ablaufdatum (TTL) und rĂ€ume alte Keys regelmĂ€Ăig auf.
- Dokumentiere klar, wie sich der Server bei âgleicher Key, andere Payloadâ verhĂ€lt (Konflikt statt still).
HĂ€ufige Stolperfallen und wie sie vermeidbar sind
Key nur auf Client-Seite âmerkenâ
Wenn der Client den Key erzeugt, aber der Server ihn nicht dauerhaft prĂŒft und speichert, ist nichts gewonnen. Der Schutz muss serverseitig passieren, sonst bleiben Race Conditions und doppelte Nebenwirkungen möglich.
Keys nicht scopen (Kollisionen zwischen Nutzern)
Ein Key sollte nie global âfĂŒr alleâ gelten. Sonst kann ein zufĂ€llig gleicher Wert (oder ein absichtlich wiederverwendeter) den falschen Response liefern. Der sichere Ansatz: Key immer zusammen mit einem Kontext speichern, z. B. User-ID oder API-Key.
Nur âbereits gesehenâ speichern, aber keine Antwort
Wenn nur gespeichert wird, dass ein Request existiert, fehlen dem wiederholenden Client wichtige Informationen (z. B. die erzeugte ID). Das fĂŒhrt zu Folgeproblemen: Der Client fragt dann andere Endpoints ab oder erstellt am Ende doch erneut. Besser: Response oder mindestens die erzeugte Ressourcen-ID ablegen.
Payload-Wechsel bei gleichem Key nicht erkennen
Wenn derselbe Key mit anderen Daten wiederkommt, ist das kein Retry, sondern inkonsistentes Verhalten im Client oder ein Bug. Ein gespeicherter Hash der relevanten Felder macht den Konflikt sichtbar und schĂŒtzt davor, versehentlich âfalscheâ Ergebnisse zurĂŒckzugeben.
Idempotency Keys und angrenzende Konzepte
Idempotency Keys lösen âdoppelt ausfĂŒhrenâ bei unsicheren POST-Requests. Sie ersetzen aber nicht andere Sicherheits- und Robustheitsmechanismen:
- FĂŒr wiederholbare Requests im Allgemeinen sind saubere Fehlerantworten entscheidend. Dazu passt API-Fehler richtig behandeln â robuste Webanwendungen Schritt fĂŒr Schritt.
- Wenn Clients automatisch retryn, hilft ein bewusster Umgang mit Timeouts und Wiederholungen. Das ergÀnzt Idempotency, ersetzt sie aber nicht.
- FĂŒr eventbasierte Systeme (Webhooks) ist das Thema eng verwandt: auch dort muss âdoppelt geliefertâ abgefangen werden. Dazu passt Webhooks robust bauen â Signaturen, Retries, Idempotency.
Entscheidungshilfe: wann sich der Aufwand lohnt
- Wenn ein Request Geld abbucht, Reservierungen auslöst oder Kontingente reduziert
- Idempotency Key fest einplanen und dokumentieren
- Wenn ein Request ânurâ Daten speichert, aber Duplikate spĂ€ter aufrĂ€umbar sind
- Idempotency Keys sind sinnvoll, aber optional â abhĂ€ngig vom Produkt und Support-Aufwand
- Wenn ein Endpoint ohnehin idempotent ist (z. B. PUT mit stabiler Resource-ID)
- Oft reicht das HTTP-Design, ein zusÀtzlicher Key ist nicht zwingend
Richtig umgesetzt werden Race Conditions bei kritischen Aktionen deutlich seltener sichtbar, weil Wiederholungen nicht mehr zu neuen Nebenwirkungen fĂŒhren. Das macht APIs stabiler, ohne Clients mit komplizierten Workarounds zu belasten.

