Why a retry can create two invoices
Billing requests an invoice for an order and stops waiting after 5 seconds. Compare two scenarios: the provider answers late, or the first request never reaches it.
A timeout doesn't tell you whether the invoice was created.
Explanation
What's going on
The key belongs to the order, not to an attempt, and is stored before the first call, so a crash and restart reuse it. A provider that supports idempotency keys returns the original result for a key it has seen.
Without retries there are no duplicates, but failed requests stay unresolved. A longer timeout only helps if the answer arrives before it expires.
In this model: one order, at most one invoice, as long as the provider remembers the key.
Assumptions
- The simulated provider remembers keys and returns the original invoice for a repeated key within its retention window.
- In scenario A the first answer always takes 45 seconds and the retry is answered immediately.
- Many real providers don't support idempotency keys. A lookup before retrying helps, but can't settle a request that is still in flight. A reference for which the provider allows at most one invoice, or reconciliation afterwards, are the reliable options. Adding a header alone prevents nothing.