Skip to content

Retry contract

Retryability is not a Boolean property of a status code. A retry decision depends on transience, idempotency, side-effect certainty, and remaining budget.

Contract

{
  "retry": {
    "retryable": true,
    "safe": true,
    "after_ms": 2000,
    "strategy": "exponential_backoff",
    "attempt": 2,
    "max_attempts": 5,
    "deadline": "2026-08-08T12:05:00Z",
    "idempotency_key": "cal-7c27b9",
    "side_effect_state": "none",
    "reconciliation_action": null
  }
}
Field Meaning
retryable Another attempt may succeed after the stated conditions are met
safe The producer has determined that replay will not create unacceptable duplicate effects
after_ms Minimum delay before another attempt
strategy Backoff strategy understood by the producer
attempt Number of the attempt that produced this status
max_attempts Maximum attempts permitted by current policy
deadline Time after which no further attempt is permitted
idempotency_key Key that allows a dependency to deduplicate an operation
side_effect_state Current knowledge of externally visible effects
reconciliation_action Machine-readable action for resolving uncertain state

Side-effect state

ASC 0.1 defines:

Value Meaning
none The producer knows no side effect occurred
possible A side effect may have occurred
confirmed The side effect occurred
unknown The producer cannot establish whether it occurred

Consumer algorithm

A consumer MUST NOT retry merely because a code is in the 5xxx class.

def should_retry(status, operation_is_idempotent, attempts_remaining):
    if not attempts_remaining:
        return False
    if status.name == "RESULT_STATE_UNKNOWN":
        return False
    return (
        status.retry.retryable
        and status.retry.safe
        and (
            operation_is_idempotent
            or status.retry.idempotency_key is not None
        )
    )

Consumers MUST also enforce local attempt, cost, and time budgets.

Unknown result state

If a potentially side-effecting operation timed out after it may have reached the dependency, the producer SHOULD emit ASC-6005 RESULT_STATE_UNKNOWN, not merely ASC-5004 TIMEOUT.

The consumer MUST reconcile using an idempotency key, external reference, or domain-specific lookup before repeating the operation. Generic retry policy MUST NOT override this rule.

Preconditions

Codes such as FAILED_PRECONDITION, HUMAN_APPROVAL_REQUIRED, and AUTHENTICATION_REQUIRED become retryable only after a named state transition. Waiting and then repeating the same request without that transition is not a valid retry strategy.