Browse documentation
Concept All API surfaces

Idempotency and retries

Retry Hodoflow operations safely by separating JSON:API response replay, webhook delivery deduplication, read retries, and permanent failures.

View as Markdown

Hodoflow has two distinct duplicate-suppression contracts and ordinary retry guidance. Do not reuse one surface's behavior as a promise for another.

JSON:API unsafe writes

Send a unique Idempotency-Key on POST, PUT, PATCH, or DELETE requests under /api/json. The key is scoped by tenant and service-account principal. The request fingerprint includes method, path, and raw body.

Idempotency-Key: dashboard-create-20260731-001
  • First request: reserves the key and runs normally.
  • Same key and same request: replays the stored response with idempotency-replayed: true.
  • Same key and different request: returns 409 idempotency_key_reused.
  • Concurrent duplicate while the first is running: returns 409 idempotency_key_in_progress.
  • A 5xx response is not retained, so a transient failure remains retryable.

Completed responses are retained for 24 hours by default; deployments can configure the window. Generate keys from a stable business operation ID, not a random value on every retry. Never put a credential or tenant secret in a key.

Webhook delivery deduplication

Webhook ingestion uses a stable sender delivery identifier from Idempotency-Key or a supported provider header. It retains accepted delivery identity for seven days. A duplicate receives 202 with {"status":"duplicate"} and no new run ID.

When no stable header exists, Hodoflow falls back to a time-bucketed hash of the trigger token and raw body. That protects short retries but is not a substitute for a provider delivery ID. See Retries and troubleshooting.

Retry matrix

Result Retry? Action
Network timeout before any response Yes Retry with the same idempotency/delivery key
429 Yes Wait the Retry-After duration, then retry
500 or 503 Usually Exponential backoff with jitter and a bounded attempt/time budget
401 Once after exchange Discard cached token, exchange, retry once; then alert
403 No Correct scopes or run-as permissions
404 No unchanged Correct path/ID or object access
409 idempotency conflict No Reconcile key reuse; do not generate a new key blindly
413 or 422 No unchanged Correct body size or validation failure

Reads are naturally repeatable, but still need bounded backoff. GraphQL factQuery is read-only and does not use JSON:API response replay. A GraphQL validation or complexity error is permanent until the document or variables change.

Operational rules

  • Cap attempts and total elapsed time.
  • Add jitter so many workers do not retry together.
  • Respect the credential-wide rate budget.
  • Preserve method, path, body bytes, and idempotency key across retries.
  • Record x-request-id, status, attempt, and non-secret operation identity.
  • Never log bearer tokens, client secrets, trigger URLs, or sensitive bodies.

Practice the contract in Perform an idempotent write.

Related documentation