Idempotency

The Crunchy Bridge API makes an effort to provide idempotent operations and primitives. Idempotency is a property of an operation dictating that it’s possible to safely retry that operation multiple times getting back the same result each time, and without having produced any additional side effects in the system.

Idempotent HTTP verbs

The HTTP specification dictates that the verbs GET, PUT, and DELETE are inherently idempotent. The Crunchy Bridge API respects those guidelines, and it’s safe to retry operations using these verbs any number of times with no additional considerations.

DELETE semantics

Most APIs implement idempotency on DELETE by simply returning a 404 Not found for a deleted object after an initial successfully processed request. This can be somewhat inconvenient for clients because it makes it impossible for them to distinguish between a deletion that previously executed versus one targeting an object that never existed in the first place.

As a small convenience feature, the Crunchy Bridge API will return 410 Gone for objects which have already been deleted, and the standard 404 Not found for objects which are completely unknown.

Idempotency keys

The POST and PATCH verbs are notably not idempotent, so some additional work is needed to make their use idempotent safe.

The Crunchy Bridge API will accept an Idempotency-Key header from clients containing a UUID value which uniquely identifies a request from their end. In the event of an interrupted transmission or other problem, the client can resend the request with the same value in Idempotency-Key and depending on where the previous request was lost, the API will either process it for the first time, or send back the stored response of when it was initially processed. The use of Idempotency-Key has the effect of making non-idempotent POST and PATCH safe for idempotent use.

For example:

  • A client tries to create a cluster by sending POST /clusters along with an idempotency key, but the request is terminated before reaching Crunchy’s servers. The client retries with the same key. This time the request is successful, the API processes it, and sends back a normal response.

  • A client tries to create a cluster by sending POST /clusters along with an idempotency key. The API processes the request, but the connection breaks as a response is being sent back to the client. The client retries with the same key. The API notes that this request has already been processed and sends back a stored response. Notably, a second cluster is not created accidentally.

Although idempotency keys are only used by the API for POST and PATCH requests, it’s safe to send them along with any verb. A robust client can integrate idempotency keys easily by simply sending the Idempotency-Key field along with every API request.

Subsequent requests made with the same idempotency key must have the same HTTP verb, path, and body payload as the original request made with that key. If a new request doesn’t match, the API will respond with a 409 Conflict and a message explaining the problem. A 409 Conflict will also be produced if an idempotency key is reused before the original request attached to it has had a chance to finish.

Along with storing the results of successful requests, idempotency keys will store the results of most unsuccessful ones as well. An initial 400 Bad request will produce the same result when its key is reused. There are a few exceptions to this rule where errors are considered to be transitory: 429 Too many requests (rate limited), 500 Internal server error, and 503 Service unavailable. Retrying any of these with the same key will prompt the API to try the operation again.

Idempotency keys have a server-side lifetime of one hour. Re-using keys after that horizon will have the effect of triggering a brand new request.

Idempotency keys must be UUIDs in a common format like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.

If an idempotency key was used, its value is mirrored back into the Idempotency-Key response header. If a stored response was replayed, the response will contain the header and value Idempotency-Replay: true.