# Bedingte API-Anfragen, die Überschreibungen durch Agenten verhindern

Ein Agent kann eine vollkommen gültige API-Anfrage erzeugen und trotzdem echten Schaden anrichten. Der Fehler entsteht, wenn er einen Datensatz liest, eine andere Instanz ihn verändert und der Agent später seine alte Kopie über den neueren Zustand schreibt. Authentifizierung verhindert das nicht. Autorisierung ebenfalls nicht. Die Anfrage stammt zwar von einem erlaubten Aufrufer, enthält aber ein überholtes Bild der Realität.

Bedingte API-Anfragen beheben genau diesen Fehler. Der Client sagt sinngemäß: «Wende diese Änderung nur an, wenn die Ressource noch die Version ist, die ich gesehen habe.» Der Server prüft diese Aussage als Teil des Schreibvorgangs. Ist sie falsch, verweigert er die Aktion, bevor sich irgendetwas ändert.

Dieser Vertrag ist bei Coding-Agenten besonders wichtig, mehr noch als bei einer Person, die sich durch ein Formular klickt. Agenten können viele Ressourcen lesen, eine Pause einlegen, Code untersuchen oder Tests ausführen und anschließend eine Gruppe von Schreibvorgängen senden, obwohl sich die Welt inzwischen weiterbewegt hat. Behandle jede folgenreiche Aktualisierung als Read-Modify-Write-Vorgang, außer die API kann nachweisen, dass es sich um ein Anhängen oder einen kommutativen Befehl handelt.

## Verlorene Änderungen entstehen in gewöhnlichen Read-Modify-Write-Abläufen

Eine verlorene Änderung entsteht, wenn zwei Schreibende vom selben alten Zustand ausgehen und der spätere Schreibvorgang die frühere Änderung löscht. Dafür braucht es weder einen Datenbankausfall noch einen böswilligen Benutzer oder ein kaputtes Netzwerk. Ein Server, der eine bedingungslose Ersetzung akzeptiert, reicht aus.

Stell dir eine als JSON bereitgestellte Bereitstellungskonfiguration vor:

```json
{
  "name": "billing-worker",
  "replicas": 3,
  "image": "registry.example/billing:2.4.0",
  "maintenanceMode": false
}
```

Ein Agent liest sie, um `replicas` vor einem Lasttest von 3 auf 5 zu erhöhen. Währenddessen setzt ein Betreiber `maintenanceMode` auf `true`, um ein Problem mit einer Warteschlange zu untersuchen. Sendet der Agent später ein vollständiges `PUT` mit seinem gespeicherten Dokument, kann er `maintenanceMode` wieder auf `false` setzen. Die Anfrage hat die Replikazahl wie beabsichtigt geändert. Gleichzeitig hat sie eine Sicherheitsentscheidung rückgängig gemacht, die der Agent nie gesehen hatte.

Eine Teilaktualisierung begrenzt den Schaden, beseitigt das Rennen aber nicht. Sendet ein Agent einen PATCH zum Ersetzen von `/replicas`, kann sich dieses Feld seit dem Lesen trotzdem geändert haben. Vor allem kann die Entscheidung, die Replikazahl auf 5 zu setzen, von anderen Feldern abhängen, die inzwischen verändert wurden. PATCH beschreibt die Form des Anfragekörpers. Es sagt nicht, auf welcher Version der Ressource dieser Körper beruht.

Darum ist «Unsere Oberfläche ändert immer nur ein Feld» kein Nebenläufigkeitskonzept. Eine Oberfläche kann das Problem eine Zeit lang verdecken, weil Menschen langsam handeln und aktuelle Seiten sehen. Ein autonomer Prozess hat keine dieser zufälligen Schutzmaßnahmen.

## Ein ETag kennzeichnet die Darstellung, die ein Client gesehen hat

Der HTTP-Antwortheader `ETag` ist ein Validator. Wenn ein Server eine Darstellung zurückgibt, kann er ein Token anhängen, das diese Version der Darstellung kennzeichnet:

```http
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "deploy-8f31c2"

{
  "name": "billing-worker",
  "replicas": 3,
  "image": "registry.example/billing:2.4.0",
  "maintenanceMode": false
}
```

Für die Zeichenfolge gibt es kein vorgeschriebenes internes Format. Sie kann eine Datenbankrevision, einen Inhaltshash oder einen undurchsichtigen generierten Wert enthalten. Clients müssen sie als undurchsichtig behandeln. Versuche nicht, aus einem Tag eine Revisionsnummer zu lesen, und erzeuge auch keinen Tag aus einem JSON-Körper. Seine Bedeutung wird vom Server festgelegt.

RFC 9110 definiert Entity-Tags und unterscheidet zwischen starken und schwachen Tags. Ein starkes ETag hat die normale Syntax mit Anführungszeichen, etwa `"deploy-8f31c2"`. Es sagt, dass die Darstellungen unter der vom Server gewählten Darstellungssemantik Byte für Byte übereinstimmen. Ein schwaches Tag beginnt mit `W/`, etwa `W/"deploy-8f31c2"`, und sagt nur, dass zwei Darstellungen für die Cache-Validierung semantisch ähnlich genug sind.

Diese Unterscheidung wird ständig verwischt. Schwache Validatoren eignen sich für viele Cache-Prüfungen bei GET. Für den Schutz eines Schreibvorgangs sind sie das falsche Werkzeug, weil sich zwei «ausreichend ähnliche» Darstellungen trotzdem in einem Feld unterscheiden können, das der Schreibvorgang zerstören würde. RFC 9110 verlangt für `If-Match` einen starken Vergleich. Veröffentlicht deine API nur schwache ETags, stellt sie kein für optimistische Nebenläufigkeit geeignetes ETag bereit.

Eine Ressource kann für verschiedene Darstellungen unterschiedliche ETags haben. Hübsch formatiertes JSON, kompaktes JSON oder über Inhaltsverhandlung ausgewählte Formate können jeweils einen eigenen Validator erhalten. Das ist zulässiges HTTP-Verhalten, für API-Clients aber unangenehm. Verwende für Schreibendpunkte nach Möglichkeit eine stabile kanonische Darstellung. Dann bleibt das ETag, das ein Client bei GET erhalten hat, auch bei PUT, PATCH und DELETE aussagekräftig.

## If-Match macht die Versionsprüfung zur Pflicht des Servers

`If-Match` setzt das erwartete ETag auf eine unsichere Anfrage. Der Server führt die Methode nur aus, wenn die aktuelle Darstellung stark mit dem angegebenen Tag übereinstimmt.

Ein Agent kann einen Datensatz lesen und den empfangenen Header behalten:

```bash
curl -i \
  -H 'Authorization: Bearer $TOKEN' \
  https://api.example.test/v1/deployments/billing-worker
```

Die Antwort enthält:

```http
ETag: "deploy-8f31c2"
```

Anschließend kann der Agent mit dem Validator aus diesem Lesevorgang genau die kleinste beabsichtigte Änderung senden:

```bash
curl -i -X PATCH \
  -H 'Authorization: Bearer $TOKEN' \
  -H 'Content-Type: application/json-patch+json' \
  -H 'If-Match: "deploy-8f31c2"' \
  --data '[{"op":"replace","path":"/replicas","value":5}]' \
  https://api.example.test/v1/deployments/billing-worker
```

Ist die Ressource noch auf dieser Version, wendet der Server den Patch an und gibt ein neues ETag zurück:

```http
HTTP/1.1 200 OK
ETag: "deploy-a19d77"
Content-Type: application/json

{
  "name": "billing-worker",
  "replicas": 5,
  "image": "registry.example/billing:2.4.0",
  "maintenanceMode": false
}
```

Hat die Änderung des Betreibers zuerst die aktuelle Version verändert, gibt der Server Folgendes zurück:

```http
HTTP/1.1 412 Precondition Failed
Content-Type: application/problem+json

{
  "type": "https://api.example.test/problems/precondition-failed",
  "title": "The deployment changed after it was read",
  "status": 412,
  "detail": "Fetch the current deployment before retrying this update."
}
```

RFC 9110 besagt, dass ein Ursprungsserver die angeforderte Methode nicht ausführen darf, wenn eine `If-Match`-Bedingung falsch ausgewertet wird. Genau diese Eigenschaft kaufst du damit ein. Die Prüfung muss in derselben atomaren Operation wie die Änderung stattfinden. Ein Handler, der die Zeile liest, eine Revision im Anwendungsspeicher vergleicht und später schreibt, hat zwischen Vergleich und Schreibvorgang weiterhin ein Rennen.

Bei einer relationalen Datenbank sieht die Implementierung oft wie eine bedingte Aktualisierung aus:

```sql
UPDATE deployments
SET replicas = :replicas,
    revision = revision + 1
WHERE id = :id
  AND revision = :expected_revision;
```

Ist die Anzahl der betroffenen Zeilen null, gibt die API 412 zurück. Ist sie eins, gibt die API das aktualisierte Dokument zurück und leitet das nächste ETag aus der neuen Revision ab. Platziere die Prüfung in der `WHERE`-Klausel oder verwende eine gleichwertige transaktionale Compare-and-Set-Funktion. Teile sie nicht in zwei Abfragen auf und nenne sie anschließend sicher.

## Versionsfelder legen denselben Vertrag in den Anwendungsdaten offen

Ein Versionsfeld ist ein Validator auf Anwendungsebene. Es gibt Clients eine sichtbare Revision, die sie im Anfragekörper, in der Abfrage oder in einem eigenen Header zurücksenden. Das kann einfacher sein, wenn Clients generierte SDKs oder Nachrichtenwarteschlangen verwenden oder wenn ihr Protokoll HTTP-Antwortheader nicht zuverlässig weitergibt.

Ein GET könnte Folgendes zurückgeben:

```json
{
  "id": "billing-worker",
  "revision": 42,
  "replicas": 3,
  "maintenanceMode": false
}
```

Die Aktualisierung kann ihre Erwartung ausdrücklich nennen:

```http
PATCH /v1/deployments/billing-worker HTTP/1.1
Content-Type: application/json

{
  "expectedRevision": 42,
  "replicas": 5
}
```

Der Server vergleicht `expectedRevision` atomar mit der gespeicherten Revision. Bei Erfolg erhöht er die Revision. Bei einer Abweichung weist er die Anfrage mit einer dokumentierten Antwort zurück, häufig mit 412, wenn das Feld als Vorbedingung dient.

Verwechsle ein Versionsfeld nicht mit einem Zeitstempel. Eine monotone ganzzahlige Revision macht die Gleichheit eindeutig. Zeitstempel werfen unbequeme Fragen auf: Mit welcher Genauigkeit speichert der Server? Können zwei Schreibvorgänge in dasselbe Zeitfenster fallen? Hat die Serialisierung den Wert verändert? Vergibt ein Replikat die Zeit anders? Einige dieser Probleme lassen sich lösen, ein Revisionszähler erfordert jedoch weniger Erklärungen.

ETags und Versionsfelder sind keine Gegenspieler. Eine API kann beides bereitstellen: Das ETag trägt die standardisierte HTTP-Bedeutung, während die Revision dem Anwendungscode hilft, Änderungen anzuzeigen oder zusammenzuführen. Beide müssen aus demselben festgeschriebenen Zustand stammen. Wenn eines Version 42 und das andere versehentlich Version 41 meint, haben Clients keine verlässliche Möglichkeit zur Wiederherstellung.

Akzeptiere nicht beliebig ein ETag oder ein Revisionsfeld, wenn beide voneinander abweichen können. Wähle für eine Route eine maßgebliche Vorbedingung oder verlange, dass beide übereinstimmen. Flexible Eingabeverträge wirken freundlich, bis ein Client einen veralteten Revisionswert im Körper mit einem frisch kopierten Header sendet und niemand weiß, welcher Aussage der Server gefolgt ist.

## If-None-Match schützt die Erstellung, nicht die veraltete Ersetzung

`If-None-Match` kehrt die Bedingung um. Die Methode darf nur fortgesetzt werden, wenn die aktuelle Darstellung mit keinem der angegebenen Tags übereinstimmt. Bei unsicheren Methoden führt eine falsche Bedingung zu 412.

Die nützlichste Änderungsform ist `If-None-Match: *`. Sie bedeutet: «Erstelle dies nur, wenn keine aktuelle Darstellung existiert.» Ein Client kann so sicher versuchen, eine Ressource mit einem festgelegten Namen zu erstellen:

```bash
curl -i -X PUT \
  -H 'Authorization: Bearer $TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'If-None-Match: *' \
  --data '{"name":"nightly-export","schedule":"0 2 * * *"}' \
  https://api.example.test/v1/jobs/nightly-export
```

Hat ein anderer Client den Auftrag bereits erstellt, weist der Server die Anfrage zurück, statt ihn stillschweigend zu ersetzen. Das ist nützlich, wenn ein Agent eine Kennung abgeleitet hat und kein bereits vorhandenes Objekt mit demselben Namen übernehmen darf.

Sende bei normaler optimistischer Nebenläufigkeitskontrolle nicht `If-Match: *`. Damit wird nur verlangt, dass irgendeine aktuelle Darstellung existiert. Ein Agent erhält dadurch die Erlaubnis, jede aktuelle Version zu überschreiben, auch eine, die er nie gelesen hat. Das schützt die Existenz, nicht vor verlorenen Änderungen.

Bei GET und HEAD unterstützt `If-None-Match` das Caching. Ein passender Tag führt normalerweise zu `304 Not Modified`, ohne Antwortkörper. Dieses Cache-Verhalten ist oft der erste Grund, aus dem Entwickler ETags kennenlernen. Daraus darf jedoch nicht folgen, dass Validatoren nur Cache-Hilfsmittel sind. Bei Schreibvorgängen hat derselbe Mechanismus deutlich schärfere Folgen.

## Eine Antwort auf einen veralteten Schreibvorgang braucht eine klare Agentenregel

Ein 412 sollte den aktuellen Änderungsplan anhalten. Die alte Annahme des Agenten ist fehlgeschlagen, und dieselbe Anfrage wird dadurch nicht wahr.

Die sichere Wiederherstellung ist kurz:

1. Rufe die aktuelle Darstellung und ihren neuen Validator ab.
2. Vergleiche die Felder oder Zustandsannahmen hinter der beabsichtigten Aktion, nicht nur das im Patch genannte Feld.
3. Wiederhole die Anfrage mit dem neuen Validator nur, wenn die Absicht ohne Neuinterpretation weiterhin richtig ist.
4. Bitte um Genehmigung oder stoppe, wenn der aktuelle Zustand Bedeutung, Umfang oder Risiko der Aktion verändert.

Der zweite Punkt wird von automatisierten Clients oft umgangen. Nehmen wir an, ein Agent wollte einen Benutzer nach dem Lesen einer Mitgliederliste aus einer Zugriffsgruppe entfernen. Dann ändert eine Person die Rolle des Benutzers von Auftragnehmer zu Incident-Responder. Nach dem erneuten Abruf kann der Agent die Entfernung weiterhin syntaktisch korrekt durchführen. Automatisch sollte er das trotzdem nicht tun, weil die Rollenänderung den ursprünglichen Plan fragwürdig macht.

Halte den Arbeitsdatensatz klein, aber vollständig: Ressourcen-URI, beobachtetes ETag oder beobachtete Revision, gelesene Felder, beabsichtigte Änderung und Antwort. Ein Tool-Runner kann diese Informationen für eine kurze Aufgabe im Speicher behalten. Ein längerer autonomer Ablauf sollte sie in seinem eigenen protokollierten Aufgabenstatus speichern. Bitte das Modell niemals, sich einen Validator nur aus Fließtext zu merken. Headerwerte in Anführungszeichen lassen sich leicht verlieren, verändern oder für die falsche Ressource wiederverwenden.

Sallyport kann den Agenten während des HTTP-Aufrufs von den API-Zugangsdaten fernhalten. Der Agent muss das ETag jedoch weiterhin als normale Anfragedaten speichern und senden. Zugangsdatenisolierung und Nebenläufigkeitskontrolle verhindern unterschiedliche Fehler, daher solltest du beide einsetzen, wenn eine Aktion Folgen hat.

## 412, 409 und 428 beschreiben unterschiedliche Fehler

Gib `412 Precondition Failed` zurück, wenn der Client einen bedingten Anfrageheader oder eine gleichwertige dokumentierte Vorbedingung gesendet hat und diese Bedingung falsch ist. Die Antwort sagt genau, dass sich die Ressource nicht mehr in dem Zustand befindet, den der Client behauptet hat.

Gib `428 Precondition Required` zurück, wenn der Server für eine Route eine Vorbedingung verlangt und der Client sie ausgelassen hat. RFC 6585 definiert diesen Status ausdrücklich, um verlorene Änderungen zu verhindern. Eine Antwort kann mitteilen, dass PATCH `If-Match` verlangt, und das aktuelle ETag zurückgeben, sofern dadurch keine vertraulichen Informationen offengelegt werden.

Gib `409 Conflict` zurück, wenn die Anfrage auch nach erfolgreicher Versionsprüfung mit dem Anwendungszustand kollidiert. Ein Client kann beispielsweise einen `If-Match`-Wert senden, der zur aktuellen Rechnung passt, während der Server die Stornierung ablehnt, weil die Zahlungsabwicklung bereits begonnen hat. Die Versionsprüfung war erfolgreich, der fachliche Befehl steht trotzdem im Konflikt mit dem Rechnungszustand.

Fasse diese Fälle nicht zu einem allgemeinen Fehler zusammen. Ein Agent sollte unterschiedlich reagieren:

- Nach 428 die Ressource abrufen und die Anfrage mit der erforderlichen Bedingung wiederholen.
- Nach 412 neu laden und die ursprüngliche Absicht erneut prüfen.
- Nach 409 den fachlichen Konflikt untersuchen und dem Lösungsweg der API folgen.

Ein hilfreicher Fehlerkörper nennt die Ressource, beschreibt die fehlgeschlagene Bedingung ohne Geheimnisse zu wiederholen und sagt dem Client, ob ein neuer GET helfen kann. Er sollte nicht so tun, als wäre eine Wiederholung harmlos. Der HTTP-Status trägt die maschinenlesbare Kategorie, der Körper liefert dem Betreiber genügend Kontext für die nächste Entscheidung.

## Last-Modified-Daten sind eine Kompatibilitätslösung

`Last-Modified` und `If-Unmodified-Since` können eine verwandte Bedingung ausdrücken: Führe die Methode nur aus, wenn sich die Ressource seit dem angegebenen Zeitpunkt nicht verändert hat. Sie bleiben dort nützlich, wo eine ältere API bereits Änderungszeiten veröffentlicht und die Einführung von Tags Zeit braucht.

Für folgenreiche Schreibvorgänge sind sie schwächer. HTTP-Daten haben eine Genauigkeit von einer Sekunde. Zwei Änderungen in derselben Sekunde können dasselbe sichtbare Datum erhalten, und ein Client weiß möglicherweise nicht, ob der gespeicherte Zeitstempel des Servers genauer ist als sein Header. Replikation, Uhren und Serialisierung bieten weitere Überraschungsmöglichkeiten.

Sendet ein Client sowohl `If-Match` als auch `If-Unmodified-Since`, hat `If-Match` nach RFC 9110 Vorrang. Das ist sinnvoll. Ein starker Validator prüft eine exakte Version, ein Datum ist eine Annäherung.

Erfinde keinen eigenen `X-If-Version`-Header, außer du hast einen Protokollgrund, den Standardheader nicht abdecken können. Benutzerdefinierte Header verbreiten sich schnell in SDKs und Proxys und werden dann zu dauerhafter Kompatibilitätsarbeit. `ETag` und `If-Match` haben bereits klare Bedeutungen, bekannte Statuscodes und Unterstützung in gewöhnlichen HTTP-Werkzeugen.

## Auch Patch-Formate brauchen eigene Prüfungen

Bedingte Header schützen die Version der Ressource. Sie prüfen nicht, ob ein Patch eine sichere Umwandlung beschreibt. Ein JSON Merge Patch, der ein ganzes verschachteltes Objekt enthält, kann trotz korrektem ETag weiterhin benachbarte Felder löschen. Ein JSON Patch kann die falsche Position eines Arrays ansprechen, wenn sich die Mitgliedschaft einer geordneten Liste geändert hat.

Verwende das Patch-Format, das zur Operation passt. JSON Patch nach RFC 6902 beschreibt Operationen wie `replace`, `add`, `remove` und `test` auf bestimmten Pfaden. Mit `test` kann es vor der Ausführung weiterer Operationen einen Wert innerhalb des Dokuments prüfen. JSON Merge Patch nach RFC 7396 beschreibt ein gewünschtes Teildokument und behandelt `null` als Löschung.

Ein ETag auf Dokumentebene sollte der äußere Schutz bleiben. Ergänze einen JSON-Patch-`test`, wenn die Operation eine feldbezogene Annahme enthält, die ausdrücklich gemacht werden sollte:

```json
[
  {"op":"test","path":"/maintenanceMode","value":false},
  {"op":"replace","path":"/replicas","value":5}
]
```

Hat ein anderer Schreibender `maintenanceMode` vor dieser Anfrage geändert, muss die Anfrage fehlschlagen, statt während der Wartung die Kapazität zu erhöhen. Die API sollte dokumentieren, welche Antwort sie bei einem fehlgeschlagenen JSON-Patch-Test zurückgibt. Viele Implementierungen verwenden 409, weil die Patch-Anweisung mit dem aktuellen Dokument kollidiert, während ein äußerer ETag-Konflikt weiterhin 412 bleibt. Diese Unterscheidung ist nützlich, wenn Clients wissen müssen, ob ihr Dokument veraltet war oder ob sie eine ungültige zustandsabhängige Anfrage gestellt haben.

Verlass dich nicht allein auf `test` in einem Patch als allgemeines Nebenläufigkeitskonzept. Damit werden nur die Pfade geschützt, an deren Prüfung du gedacht hast. Ein starkes ETag schützt die Version der Darstellung, auf der der Agent seinen Plan tatsächlich aufgebaut hat.

## Server müssen die Vorbedingung an der Schreibgrenze erzwingen

Ein API-Vertrag, der `If-Match` nur empfiehlt, wird unter Zeitdruck versagen. Ein Client lässt ihn aus, ein anderes SDK vergisst seine Weitergabe und der anfällige Endpunkt wird derjenige, den Agenten anhand von Beispielen entdecken. Verlange die Bedingung für Aktualisierungen, bei denen eine veraltete Ersetzung spürbare Kosten verursacht.

Der Handler sollte fehlende Bedingungen ablehnen, bevor er Nebenwirkungen ausführt. Danach muss er den erwarteten Validator an den Speichervorgang übergeben, der den Zustand verändert. Bei einer Ressource, die von mehreren Tabellen oder einer externen Steuerungsebene abhängt, müssen Vergleich und Zustandsänderung in einer Transaktion stattfinden oder die Compare-and-Set-Operation des Anbieters verwenden. Kann der Anbieter das nicht leisten, darf deine API für diesen Schreibvorgang keinen Schutz vor verlorenen Änderungen versprechen.

Teste das Rennen bewusst. Lege eine Ressource mit Revision 7 an. Lass Client A und Client B sie beide per GET lesen. Lass A mit `If-Match: "7"` patchen und prüfe, dass er Revision 8 erhält. Lass anschließend B mit `If-Match: "7"` patchen und prüfe, dass er 412 erhält und seine gewünschte Änderung nicht aufgetaucht ist. Wiederhole den Test mit DELETE, vollständigem PUT und jeder Sammelaktion, die eine Ressource nach einem vorherigen Lesevorgang schreibt.

Teste auch die gefährlichen Abkürzungen: Ein fehlendes `If-Match` muss auf geschützten Routen 428 erhalten, `If-Match: *` darf nicht als Schutz vor veralteten Schreibvorgängen dargestellt werden und ein schwaches ETag darf einen starken Vergleich nicht bestehen. Diese Tests finden Regressionen, wenn ein neuer Endpunkt die normale Repository-Methode umgeht.

## Der sichere Weg muss einfacher sein als das Überschreiben

Die API sollte bei jedem GET veränderlicher Ressourcen ETags zurückgeben, erforderliche Bedingungen neben jeder unsicheren Operation dokumentieren und SDK-Methoden die Validatoren selbstverständlich mitführen lassen. Ein Client sollte keine rohen Header aus einem schwer zugänglichen Antwortobjekt herausfiltern müssen, um die Arbeit eines anderen Schreibenden nicht zu beschädigen.

Trenne bei Agenten Planung und Ausführung. Lies das Ziel, speichere seinen Validator, beschreibe die beabsichtigte Änderung und sende den bedingten Aufruf. Wenn sich irgendeine Beobachtung ändert, verwerfe den geplanten Schreibvorgang, außer der Agent kann zeigen, dass die Änderung irrelevant ist. Diese Regel klingt vorsichtig, weil sie vorsichtig ist. Die Alternative wäre, einem automatisierten Prozess zu erlauben, auf Fakten zu handeln, von denen er weiß, dass sie veraltet sind.

Beginne mit Endpunkten, bei denen eine überschriebenen Änderung jemanden aufschrecken würde: Bereitstellungseinstellungen, Zugriffskontrolle, Kundendatensätze, Zahlungsstatus und Metadaten zu Geheimnissen. Füge `If-Match` hinzu, lasse eine fehlende Vorbedingung fehlschlagen und teste zwei Schreibende gegen die Route. Sobald der Server veraltete Schreibvorgänge standardmäßig ablehnt, führt die Geschwindigkeit eines Agenten nicht mehr dazu, dass gewöhnliche Nebenläufigkeit stillen Schaden anrichtet.
