ADR 0006: Idempotency For Write Operations
Ratification
Adopted before ADR 0018. There was no separate ratification process. Git history for this file on main is the record.
- Discussion Issue: not recorded (before ADR 0018)
- Merge PR: see git history for this file
- Accepted: as merged to
main
Context
Why this matters: Networks drop packets; clients time out and retry; mobile apps tap “submit” twice. If the server treats every retry as a new action, you get duplicate users, double charges, or conflicting updates. Idempotency means: “send the same logical request again with the same key, and the server does not apply the side effect twice—it returns the same outcome as the first success.”
This is usual for payment and write APIs; we use it for critical writes so integrations stay safe when clients retry.
Decision
- All critical write operations must support idempotent retry behavior.
- Client sends
Idempotency-Keyfor write requests. - Server deduplicates by
(endpoint, idempotency_key, payload_hash). - Same key + same payload replays original success response.
- Same key + different payload returns conflict error.
Initial Implementation
POST /api/v1/user,PUT /api/v1/user/{system_user_id}, andPATCH /api/v1/user/{system_user_id}requireIdempotency-Key.- Missing key returns
400 IDEMPOTENCY_KEY_REQUIRED. - Key reuse with different payload returns
409 IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_PAYLOAD. - Dedup records are persisted in DB table
idempotency_keysto survive service restarts.
Contract Impact
- Write endpoint OpenAPI docs must document idempotency header and conflict behavior.
- Tests must include replay scenario and key-conflict scenario.
- Runbooks should cover idempotency key misuse and retry errors.
Consequences
Positive
- Safe retries for transient failures and network timeouts.
- Reduced risk of duplicate writes in real integrations.
- Explicit, testable retry contract for client teams.
Trade-offs
- Additional request discipline for client integrations.
- Persistent dedup store introduces additional DB writes for write operations.
Page history
| Date | Change | Author |
|---|---|---|
| Added Page history section (repository baseline). | Ivan Boyarkin |