Prompt and context
Payment, ticket, and resource-creation APIs can execute a request while losing its response. Customers want Idempotency-Key for safe retries. Decide whether to launch it and define the promise, target customers, metrics, cost, and rollback.
What the interviewer tests
Can you turn a protocol capability into a verifiable product contract: supported operations, key lifetime, parameter mismatches, duplicate responses, and the trade-off among reliability, storage cost, and developer experience?
Questions to clarify
Clarify whether the painful side effect is a duplicate charge, resource, or notification; then ask about request volume, retry window, multi-region needs, and retention rules. Separate server deduplication from business completion so the promise does not become an unsupported exactly-once claim.
30-second answer
“I would launch bounded idempotency for high-risk writes, not promise exactly-once for every endpoint. The contract should define key format, tenant scope, retention window, parameter fingerprint, and duplicate response; the same key with different parameters must conflict. I would pilot payments and resource creation, measure duplicate side effects, safe-retry success, storage cost, and support cases, then expand through an opt-in canary with clear 409/422 semantics.”
Step-by-step deep dive
Define user value
Make “safe to retry after a timeout” the outcome and prioritize POST operations with financial or resource side effects. Read-only calls and naturally idempotent PUTs do not need this complexity for marketing reasons.
Write the contract boundary
Define tenant-scoped uniqueness, length limits, retention, and retryable states. Store the first status and body; the same key with different parameters must conflict instead of silently reusing a wrong result.
Connect to the business transaction
The deduplication record must share a reliable transaction with the side effect or use a recoverable outbox. A cache hit does not prove downstream settlement; asynchronous work should return a queryable operation id.
Design errors and compatibility
Distinguish in-progress, succeeded, failed, and expired. SDKs, docs, and gateways must forward the key consistently. Older clients can continue working, but should not receive an implicit retry guarantee.
Choose metrics and cost
Track duplicate side-effect rate and safe-retry success as primary metrics; guardrails include key-store capacity, P95 latency, conflict rate, and support volume. Set TTL and storage by tenant risk instead of retaining responses forever.
Roll out in stages
Start in one region, payment sandbox, and internal SDK. Validate hit rate with shadow dedup logs, then let a small tenant cohort opt in. If responses diverge, storage grows out of control, or a downstream lacks transaction support, disable the new entry point while preserving the old path.
Model answer
I would position idempotency keys as a retry-safety contract for high-risk writes. Start with payments and resource creation; define tenant scope, key format, retention, parameter fingerprint, and duplicate responses. Conflicting parameters must fail, and asynchronous side effects need a queryable operation id. Measure duplicate side effects, safe-retry success, P95 latency, conflict rate, and storage cost. Pilot in a sandbox and opt-in canary, and do not expand the promise when transaction or downstream support is missing.
Common mistakes
Promising exactly-once
An idempotency key mainly removes duplicate client submissions; it cannot cover an unrecoverable downstream side effect. State at-most-once handling and final-state lookup explicitly.
Retaining keys forever
Permanent retention creates cost, privacy, and cleanup issues. Define TTL by risk and document post-expiry behavior.
Ignoring parameter changes
Returning the first result for a different request hides client bugs. Store a parameter fingerprint and return a conflict.
Implementing only a gateway cache
Gateway caching can be detached from the business transaction. The dedup record needs reliable consistency or recoverable compensation.
Follow-up questions
Why not support every POST?
Side effects and costs differ. Cover high-risk scenarios first instead of imposing a complex contract on low-value endpoints.
What if the first request is still running?
Return an explicit in-progress state and operation id for polling or subscription; do not execute a second side effect concurrently.
How do you keep keys consistent across regions?
Start with one primary region or tenant sharding. Multi-region support requires consistent dedup storage and failure drills, not cache replication alone.
Can failed responses be reused?
The contract must distinguish retryable transient failures from final failures and document whether status and body are cached. Stripe stores the first result, so customers must understand TTL and error semantics.