Skip to content

Commit

Permalink
Improved Idempotency-Key description.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholas-s-perkins committed Dec 12, 2024
1 parent 02bd31e commit 561b2be
Showing 1 changed file with 12 additions and 27 deletions.
39 changes: 12 additions & 27 deletions standards/request-response.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,25 +444,23 @@ Access-Control-Allow-Methods: *

<hr />

```note
**KEEP AN EYE ON IT**: The [Idempotency-Key Request header](https://tools.ietf.org/id/draft-idempotency-header-01.html) is in an experimental state but getting lots of attention as a pattern of making fault-tolerant resilient requests for traditionally non-idempotent methods like `POST`.
```
#### [Idempotency-Key Request header](https://datatracker.ietf.org/doc/html/draft-idempotency-header-01)
**Type**: Request

#### Idempotency-Key
The HTTP Idempotency-Key request header field can be used to carry an "idempotency key" to make non-idempotent HTTP methods such as POST or PATCH fault-tolerant.
This is both a standard and non-standard header, as there is common usage of it, but no accepted spec for it.
**Support**: OPTIONAL

**Description**:
The HTTP Idempotency-Key request header field can be used to carry an "idempotency key" to make non-idempotent HTTP methods such as POST or PATCH fault-tolerant.
This is an experimental header, as there is common usage of it, but no accepted spec for it.
`Idempotency-Key` should typically be a V4 UUID as a string, or another random string with enough entropy to avoid collisions, and
should be no longer than 255 characters long.
A suggested regex for a generic validator:
```regexp
[a-z0-9-]{20,255}
```
An API must in some way persist the Idempotency-Key in a stateful way.
An API must in some way persist the Idempotency-Key in a stateful way to manage the idempotency.
It is common to include the key as part of the primary key or as a secondary index for the resource.

An API, when faced with a conflict, may return any standard success `2xx success` if the endpoint is idempotent,
or a `409 Conflict` if the endpoint is not idempotent.
- The header value **MUST** follow this regex format: `[a-z0-9-]{20,255}`
- An API **MUST** return a `400` when the header value is an invalid format.
- On conflict, an API **MUST** return a `2xx` if the endpoint is idempotent, or a `409` if the endpoint is not idempotent.
- An API **MAY** treat this as the final primary ID of the resource, or as some part of the ID.

```
// CORRECT
Expand All @@ -471,22 +469,9 @@ Idempotency-Key: d4f885c5-2196-49c0-ba69-bc70008585ad-custom
// INCORRECT
Idempotency-Key: a // not enough entropy
Idempotency-Key: KG5Lxw!@#$&*()FBepaKHyUD // special characters can be limiting for storage and url reference
Idempotency-Key: KG5Lxw!@#$&*()FBepaKHyUD // non-url-safe special characters can be limiting for usage or later reference
```

This is a common technique for avoiding retry-loops creating duplicate entries.
For example:
1. User calls API (Idempotency-Key=d4f885c5-2196-49c0-ba69-bc70008585ad)
2. API creates resource(key=d4f885c5-2196-49c0-ba69-bc70008585ad)
3. API responds 201
4. Response dies in transit, user receives 5xx
5. User calls API again (Idempotency-Key=d4f885c5-2196-49c0-ba69-bc70008585ad)
6. API notices resource(key=d4f885c5-2196-49c0-ba69-bc70008585ad) exists, responds with a 201

It is also a powerful technique to bind a workflow to an idempotency key to avoid duplicate entries or breakage.
`Idempotency-Key` can be bound to various message IDs for a system, ensuring that if the message is replayed,
the stateful interactions are all idempotent to that message ID.

### Custom Headers

- Custom Headers **MAY** be used and created as necessary.
Expand Down

0 comments on commit 561b2be

Please sign in to comment.