Skip to content

No client-supplied idempotency key on write endpoints #145

Description

@LKSNDRTMLKV

What is missing

No write endpoint accepts a client-supplied idempotency key. A client that retries a POST after a timeout has no way to say "this is the same request", and no way to learn whether the first attempt landed.

The internal outbox makes our side of event delivery idempotent. That does nothing for the caller: a passport create that times out at the network layer may or may not have created a passport, and the only recovery is to list and compare.

Why this is filed rather than built

It is a design pass, not a feature, and it was mis-sized when first raised. Four things need deciding before any code:

  1. Scope. Every mutating route, or only non-idempotent ones? PUT and lifecycle transitions are already idempotent by shape; POST /dpp and evidence generation are not. A key on a route that does not need one is noise that still costs a storage row.
  2. Storage and retention. Keys need a store, which means a migration. How long is a key honoured — long enough to cover a client's retry budget, short enough not to grow without bound? A key retained forever is a slow leak; one retained for a minute does not survive an outage, which is the case it exists for.
  3. Same key, different body. The interesting failure. Returning the first result silently is wrong — the caller asked for something else. 422 is the usual answer, and it requires storing a fingerprint of the request body, not just the key.
  4. What is replayed. The stored response, or a pointer to the created resource? Replaying a stored body means storing bodies; returning a pointer means the second caller gets a different shape from the first.

Why it is worth doing before there are clients

Retrofitting idempotency after clients exist is a breaking change to their retry behaviour, or a silent one, which is worse. Deciding it while the only consumers are ours is the cheap moment. That argument is the reason this is filed rather than dropped.

Done when

A design note exists answering all four questions above; then: a repeated request carrying the same key returns the first outcome without creating a second resource, a reused key with a different body is refused rather than silently replayed, and keys expire on a stated schedule with a test that proves expiry.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions