All updates
QAFrontend

Safer write requests: idempotency keys and automatic retries for transient failures (QA)

PR #1040pixbox-supportJun 8, 2026 · 17:14 UTC
QAJun 8, 2026

Executive summary

Promotes the latest frontend dev work into the QA environment. The notable change is a new shared HTTP layer that attaches a stable idempotency key to every write request (create/update/delete) and automatically retries on transient backend conditions, preventing duplicate writes when the network hiccups or the server is briefly overloaded. This is wired into all four DSM web apps (Admin, Mail, Vendor, and the auth/SSO client).

Why this was needed

When a write request (POST/PUT/PATCH/DELETE) failed due to a network blip, a timeout, or temporary server overload (HTTP 429/503/504), the app had no safe way to retry. A blind retry risked creating duplicate records or applying an action twice. This change implements the agreed backend "Idempotency & Client Retry Contract" on the client so retries are safe and deduplicated by the server.

Client / user impact

Users experience fewer failed actions during brief connectivity or load issues, because eligible write operations are retried automatically. Because each logical operation reuses one idempotency key across retries, the backend can replay the original successful result instead of performing the action again, so users should no longer see duplicate items or double-applied changes from retries. The behavior is consistent across Admin, Mail, Vendor, and login/SSO flows.

Technical scope

  • New shared module packages/http-client/src/idempotency-retry.ts (399 lines) exporting installIdempotencyRetry() plus header/code constants and event types.
  • Adds request/response axios interceptors that: generate one stable Idempotency-Key (UUIDv4, with non-crypto fallback) per logical mutation and reuse it across retries; retry only mutating methods on network errors/timeouts, 429/503/504, and 409 IDEMPOTENCY_IN_PROGRESS.
  • Retry policy: up to 4 total attempts, exponential backoff with full jitter (250 ms base, 8 s cap), honoring the Retry-After header as a delay floor; skips user-canceled requests.
  • Detects server-replayed responses via the Idempotent-Replay header and exposes an optional onEvent hook for diagnostics/analytics.
  • Wired in via installIdempotencyRetry(...) in packages/http-client (client.ts, index.ts), packages/auth-client, and the Admin, Mail, and Vendor app HTTP clients (carries source PR #1039).

Risk & mitigation

Low-to-moderate, isolated to the HTTP transport layer. Main risks: a write being retried that the server did not actually deduplicate (would require a missing/mismatched key), or unexpected user-visible latency from backoff delays under failures. Mitigations: retries are restricted to mutating methods and an explicit allowlist of transient statuses, canceled requests are never retried, attempts are capped at 4, and caller-supplied idempotency keys are preserved. The contract relies on the backend honoring the same Idempotency-Key.

QA validation focus

  • Confirm normal create/update/delete flows in Admin, Mail, Vendor, and login/SSO still succeed unchanged.
  • Simulate transient failures (429/503/504, network drop/timeout) on a write and verify it retries and ultimately succeeds without creating a duplicate record or double-applying the action.
  • Verify GET/read requests are never retried by this logic and that user-canceled requests are not replayed.
  • Confirm the same Idempotency-Key is sent on the first attempt and all retries, and that a server replay (Idempotent-Replay) is handled cleanly.
  • Sanity-check that retry backoff does not introduce excessive delays and that the attempt cap (max 4) is respected.