Mental model: the idempotency key is a stable name for a business operation. The first request with that key records a decision; every later request with the same key returns the decision that already exists.
Evaluate vs Record — Idempotency applies to
record, the endpoint that persists a decision. evaluate is stateless and stores nothing, so it has nothing to deduplicate.How it works
When you callPOST /v1/decisions/record with an idempotency_key, MeshQu checks whether a decision already exists with that key for your tenant:
The second call returns the stored decision without running policies again, so retries are both safe and cheap.
Recording with an idempotency key
The TypeScript SDK requires
idempotency_key on record() and throws if it is missing or blank. The REST API treats it as optional but strongly recommended — a record call without a key still succeeds, it just won’t be deduplicated. For any workflow that can retry (which is most of them), always supply one.Choosing good keys
A key should uniquely and deterministically identify the business operation, so that a retry of the same operation produces the same key. Good keys — derived from a stable business identifier:Key format
A key, once used, is bound to that decision permanently within the tenant. There is no expiry, so a retry months later still returns the original decision. If a decision genuinely needs to be re-made (for example after corrected input data), use a new key with a version suffix:
Safe-retry pattern
Treat both200 and 201 as success. Retry only on server errors (5xx) and network failures — never on client errors (4xx), which indicate a request that won’t succeed on retry.
Common patterns
Queue processing — use the message ID so reprocessing a redelivered message is a no-op:Verifying a key was used
Recorded decisions carry theiridempotency_key. List recent decisions and filter:
Related
- Integration Patterns — where recording fits in your request flow.
- Decision Chains — grouping related decisions into an ordered sequence.