Zurück zum Wiki

Idempotenz

Idempotenz beschreibt eine Eigenschaft von Operationen, die fuer die Stabilitaet verteilter Systeme entscheidend ist: Eine Operation ist idempotent, wenn ihre mehrfache Ausfuehrung exakt denselben Effekt hat wie ihre einmalige Ausfuehrung. Du kannst sie also beliebig oft wiederholen, ohne dass sich am Endzustand etwas aendert. Das klingt akademisch, hat aber sehr handfeste Konsequenzen: Idempotenz ist der Mechanismus, der verhindert, dass ein Kunde versehentlich zweimal belastet wird, wenn das Netzwerk waehrend einer Zahlung kurz aussetzt. Fuer jeden, der eine API betreibt, ueber die Geld, Bestellungen oder andere kritische Vorgaenge laufen, ist Idempotenz keine Kuer, sondern Pflicht.

Warum Idempotenz im Netzwerk so wichtig ist

Verteilte Systeme haben ein grundlegendes Problem: Wenn ein Client eine Anfrage schickt und keine Antwort bekommt, weiss er nicht, ob die Anfrage angekommen und verarbeitet wurde oder ob sie unterwegs verloren ging. Die Antwort koennte ebenso verloren gegangen sein wie die Anfrage selbst. Der Client steht vor einer unangenehmen Wahl: nicht erneut senden (und riskieren, dass die Operation nie ausgefuehrt wurde) oder erneut senden (und riskieren, sie doppelt auszufuehren). Genau hier loest Idempotenz das Dilemma: Ist die Operation idempotent, kann der Client gefahrlos so oft wiederholen, bis er eine Bestaetigung erhaelt. Im schlimmsten Fall wurde die Operation mehrfach empfangen, aber nur einmal wirksam.

Man unterscheidet dabei gern drei Zustellgarantien: "At-most-once" (hoechstens einmal, aber moeglicherweise gar nicht), "At-least-once" (mindestens einmal, aber moeglicherweise doppelt) und "Exactly-once" (genau einmal). Echtes "Exactly-once" ist auf Netzwerkebene extrem schwer bis unmoeglich zu garantieren. Der pragmatische und in der Industrie ueberwiegend genutzte Weg ist deshalb: "At-least-once"-Zustellung kombiniert mit idempotenter Verarbeitung. Das Ergebnis fuehlt sich fuer den Anwender wie "Exactly-once" an, ist aber technisch deutlich einfacher und zuverlaessiger umzusetzen. Idempotenz ist damit der praktische Schluessel zu einer Garantie, die sonst kaum erreichbar waere.

Dieses Muster steckt ueberall in zuverlaessiger Software: in automatischen Retry-Mechanismen, in Message-Queues mit "At-least-once"-Zustellung, in Webhook-Empfaengern und in Zahlungs-Pipelines. Ohne Idempotenz fuehrt jeder dieser Wiederholungsmechanismen frueher oder spaeter zu Doppelbuchungen, doppelten Bestellungen oder inkonsistenten Datenstaenden.

Ein konkretes Szenario aus dem Onlinehandel

Stell dir einen Kunden vor, der im Checkout auf "Jetzt kaufen" klickt. Die Anfrage erreicht deinen Server, die Bestellung wird angelegt und die Zahlung ausgeloest — doch genau in diesem Moment bricht die Mobilfunkverbindung des Kunden ab, bevor die Erfolgsmeldung bei ihm ankommt. Der Kunde sieht einen Ladekreis, wird ungeduldig und klickt erneut. Ohne Schutzmechanismus legt dein System jetzt eine zweite Bestellung an und bucht ein zweites Mal ab. Das Resultat: ein veraergerter Kunde, ein Support-Ticket, eine Ruecküberweisung und im schlimmsten Fall eine negative Bewertung. Mit Idempotenz dagegen erkennt der Server die Wiederholung, liefert das Ergebnis der ersten Bestellung zurueck und der Kunde sieht einfach seine Bestellbestaetigung — als waere nichts gewesen. Genau dieser unsichtbare Schutz ist es, der robuste Systeme von fragilen unterscheidet.

Idempotente und nicht-idempotente HTTP-Methoden

Im Kontext einer REST-API ist genau definiert, welche HTTP-Methoden idempotent sein sollen:

  • GET, HEAD, OPTIONS — idempotent und zusaetzlich "sicher" (veraendern den Zustand gar nicht).
  • PUT — idempotent: Dieselbe Ressource mit denselben Daten zu ueberschreiben, fuehrt immer zum selben Ergebnis.
  • DELETE — idempotent: Eine bereits geloeschte Ressource erneut zu loeschen, aendert nichts mehr am Zustand.
  • POSTnicht idempotent: Zweimal gesendet, entstehen zwei Datensaetze. Genau das macht POST gefaehrlich bei Wiederholungen.
  • PATCH — nicht garantiert idempotent: haengt davon ab, wie das Update formuliert ist (ein absolutes "setze Preis auf 10 Euro" ist idempotent, ein relatives "erhoehe Preis um 10 Prozent" nicht).

Diese Festlegung stammt aus der HTTP-Spezifikation und ist keine Empfehlung, sondern ein Vertrag: Clients, Proxies und Caches verlassen sich darauf. Ein Proxy darf eine fehlgeschlagene GET-Anfrage automatisch wiederholen, weil GET als idempotent gilt — bei POST waere das fatal.

Der Idempotency-Key: das praktische Werkzeug

Was aber, wenn du eine inhaerent nicht-idempotente Operation wie "lege eine neue Bestellung an" oder "fuehre eine Zahlung aus" sicher wiederholbar machen willst? Hier kommt der Idempotency-Key ins Spiel. Das Prinzip: Der Client generiert vor der Anfrage einen eindeutigen Schluessel (meist eine UUID) und schickt ihn als Header mit. Der Server merkt sich diesen Schluessel zusammen mit dem Ergebnis der Operation. Kommt eine zweite Anfrage mit demselben Schluessel an, fuehrt der Server die Operation nicht erneut aus, sondern liefert das gespeicherte Ergebnis der ersten Ausfuehrung zurueck.

Das prominenteste Beispiel ist die Stripe-API: Sie unterstuetzt einen Idempotency-Key-Header fuer alle POST-Anfragen. Schickt deine Anwendung eine Zahlung mit einem Schluessel und bekommt wegen eines Timeouts keine Antwort, kann sie die identische Anfrage mit demselben Schluessel wiederholen — Stripe garantiert, dass der Kunde nur einmal belastet wird. Auch PayPal, die Adyen-API und viele andere Zahlungsdienstleister bieten vergleichbare Mechanismen. Im E-Commerce, etwa bei einer Shopware-Integration, ist dieser Header das Standardmittel, um Doppelbestellungen bei wackeligen Verbindungen zu verhindern.

Wichtig fuer das Verstaendnis: Der Idempotency-Key bezieht sich immer auf eine konkrete Absicht. Generiert der Client fuer jeden echten Bestellversuch einen neuen Schluessel, aber fuer jede Wiederholung desselben Versuchs denselben, funktioniert der Schutz wie gewuenscht. Verwendet er versehentlich fuer zwei tatsaechlich unterschiedliche Bestellungen denselben Schluessel, wuerde die zweite faelschlich als Wiederholung erkannt und unterdrueckt. Die korrekte Generierung des Schluessels auf der Client-Seite ist also genauso Teil des Designs wie die Pruefung auf der Server-Seite — beide Haelften gehoeren zusammen gedacht.

Wie ein Idempotency-Key serverseitig funktioniert

Die serverseitige Umsetzung folgt einem klaren Ablauf, den du dir wie eine Schleuse vorstellen kannst:

  1. Anfrage mit Idempotency-Key trifft ein.
  2. Server prueft, ob der Schluessel bereits gespeichert ist.
  3. Ist er neu: Operation ausfuehren, Ergebnis zusammen mit dem Schluessel speichern, Ergebnis zurueckgeben.
  4. Ist er bekannt: gespeichertes Ergebnis zurueckgeben, ohne die Operation erneut auszufuehren.
  5. Laeuft eine erste Anfrage mit dem Schluessel noch, wird die zweite blockiert oder mit einem Konflikt-Status abgewiesen, um Race Conditions zu vermeiden.

Wichtig ist, dass die Speicherung des Schluessels und die eigentliche Operation transaktional zusammenhaengen — sonst entsteht ein Fenster, in dem die Operation lief, der Schluessel aber noch nicht gespeichert war. Die gespeicherten Schluessel bekommen ueblicherweise eine Ablaufzeit (etwa 24 Stunden), damit der Speicher nicht unbegrenzt waechst.

Idempotenz im eigenen Backend umsetzen

Du musst nicht auf fertige Dienste warten, um Idempotenz zu bekommen — in einem eigenen Backend (etwa auf Basis von NestJS oder Node.js) lassen sich verschiedene Strategien kombinieren. Welche passt, haengt vom Anwendungsfall ab:

Gaengige Strategien, um Operationen idempotent zu machen, und ihre typischen Einsatzgebiete
StrategieFunktionsweiseTypischer Einsatz
Idempotency-KeyClient schickt eindeutigen Schluessel, Server speichert Ergebnis pro SchluesselZahlungen, Bestellungen, kritische POSTs
Natuerlicher Schluessel / Unique ConstraintDatenbank verhindert Duplikate ueber eine eindeutige SpalteAnlegen von Datensaetzen mit fachlicher ID
Upsert (INSERT ... ON CONFLICT)Einfuegen oder aktualisieren in einem SchrittSynchronisation, Importe
ZustandspruefungOperation nur ausfuehren, wenn der Zielzustand noch nicht erreicht istStatuswechsel, Workflows

In der Praxis ist die Kombination aus einem Idempotency-Key fuer die Schnittstelle nach aussen und einem Unique Constraint in der Datenbank als zweite Verteidigungslinie besonders robust. Selbst wenn die Anwendungslogik einmal einen Fehler macht, faengt die Datenbank das Duplikat noch ab. Diese Verteidigung in der Tiefe ist genau die Art von Sorgfalt, die sich im Produktivbetrieb auszahlt — meist genau dann, wenn man es am wenigsten erwartet.

Idempotenz jenseits von HTTP

Das Konzept ist aelter als das Web und stammt aus der Mathematik: Eine Funktion ist idempotent, wenn f(f(x)) = f(x) gilt. Der Betrag einer Zahl ist ein einfaches Beispiel — ihn zweimal zu nehmen aendert nichts. In der Software begegnet dir Idempotenz weit ueber REST hinaus: bei der Verarbeitung von Nachrichten aus einer Queue (Kafka, RabbitMQ, SQS liefern oft "mindestens einmal", also muss der Konsument doppelte Nachrichten vertragen), beim Empfang von Webhooks (die meisten Anbieter senden bei Unsicherheit erneut), bei Datenbank-Upserts (INSERT ... ON CONFLICT) und bei Infrastruktur-als-Code-Werkzeugen wie Terraform oder Ansible, deren gesamtes Versprechen darin besteht, denselben gewuenschten Zustand bei jedem Durchlauf herzustellen.

Dieser rote Faden — "wiederhole gefahrlos, bis es sicher geklappt hat" — ist eines der wichtigsten Denkmuster fuer robuste, verteilte Software ueberhaupt. Wer Systeme so entwirft, dass moeglichst viele Operationen idempotent sind, macht das gesamte System fehlertoleranter, einfacher zu betreiben und leichter zu testen. Denn idempotente Operationen darf man bedenkenlos wiederholen, was Retry-Logik, Monitoring und Wiederanlauf nach Stoerungen drastisch vereinfacht. In der Architekturberatung ist "Ist diese Operation idempotent?" deshalb eine der ersten Fragen, die wir bei der Auslegung kritischer Schnittstellen stellen.

Eine technische Vertiefung zur Definition findest du in der englischsprachigen Wikipedia.

Haeufige Fragen zu Idempotenz

Was bedeutet idempotent einfach erklaert?
Eine Operation ist idempotent, wenn es egal ist, ob du sie einmal oder mehrmals ausfuehrst — das Ergebnis bleibt gleich. Eine Datei zu loeschen ist idempotent; ihr Geld abzubuchen ohne Schutzmechanismus nicht.

Ist GET idempotent?
Ja. GET ist sogar "sicher", veraendert also den Serverzustand gar nicht. Mehrfaches Lesen liefert (abgesehen von zwischenzeitlichen Aenderungen) dasselbe Ergebnis.

Warum ist POST nicht idempotent?
Weil jeder POST per Definition eine neue Ressource anlegt. Zweimal gesendet entstehen zwei Datensaetze. Mit einem Idempotency-Key laesst sich POST aber wiederholbar machen.

Was ist ein Idempotency-Key?
Ein eindeutiger Schluessel (meist eine UUID), den der Client mit der Anfrage schickt. Der Server fuehrt die Operation pro Schluessel nur einmal aus und liefert bei Wiederholungen das gespeicherte Ergebnis.

Brauche ich Idempotenz wirklich?
Sobald Anfragen Geld bewegen, Bestellungen anlegen oder andere nicht-umkehrbare Effekte haben und ueber unzuverlaessige Netze laufen: ja. Sie ist die guenstigste Versicherung gegen Doppelausfuehrungen.

Weiterführende Artikel