A timeout does not always mean an operation failed. A request may reach a remote system, create an order, and then lose its response before your integration receives it. If the integration sends the same request again, the business may get two orders, two invoices, or two notifications.

Idempotency is a practical design pattern for this uncertainty. It gives one business operation a stable identity so that a retry can be recognized as a retry instead of treated as new work. It does not remove every integration risk, but it gives developers and operations teams a clear boundary for making retries safer.

Start with the business operation, not the HTTP verb

Idempotency means that repeating the same operation produces the same intended result rather than adding another side effect. GET, PUT, and DELETE are generally defined as idempotent HTTP methods, while POST commonly creates a new resource. That distinction is useful, but it is not enough for a real workflow.

Ask what the business is trying to do: create one order, record one payment request, send one fulfillment instruction, or apply one status change. Each should have an operation identity that survives a network timeout. A retry of “create order from checkout 8472” should be distinguishable from a genuinely new checkout.

Use an idempotency key with the right scope

An idempotency key is a unique value attached to one logical operation. It might be generated when an order enters an integration, then carried through every retry of that order. The key should not be regenerated just because the HTTP request is being attempted again.

Store the key with enough context to answer three questions: what operation did it represent, what input was used, and what result was recorded? A small integration might use a database table with the key, operation type, request fingerprint, processing status, response reference, and timestamps. A queue or durable workflow store can hold the same information when the integration already uses one.

Scope matters. A key for “send invoice 8472 to accounting” should not accidentally collide with “send invoice 8472 to the customer.” Include the operation name and source record in the design, even if the external API only receives the opaque key.

Define the duplicate behavior explicitly

When a request arrives with a key already in the store, the service needs a deliberate response. If the earlier operation succeeded, return the recorded result or a reference to it. If it is still running, return an in-progress state that the caller can poll or handle through its queue. If it failed before the side effect began, allow a controlled retry.

Do not silently treat a reused key with different business data as a new request. Compare a request fingerprint or the relevant fields and reject the mismatch for review. Otherwise, a programming error could reuse a key for a different customer or amount while appearing to be a safe retry.

External services implement these contracts differently. For example, Stripe documents idempotency keys for POST requests and says it saves the first result for a given key, while also noting cases such as validation failures where execution did not begin. That is a useful model, not a reason to assume every vendor behaves the same way. Read the target API documentation and record its retention period, conflict behavior, and error semantics.

Protect the boundary around the side effect

The hardest failure window is between the side effect and the record that says it happened. A local database transaction cannot automatically cover a remote API. If the remote system creates the order and your process crashes before saving the response, the next attempt needs a way to discover the existing result.

Use an outbox or durable work record for the local side, and prefer a remote API that accepts a client request ID or idempotency key. After a timeout, query by that identity when the API supports it. If it does not, build a reconciliation step using a safe reference such as an external order number, rather than immediately issuing another create request.

This is also where “exactly once” deserves caution. Across independent systems, it is usually more realistic to design for at-least-once delivery plus deduplication and reconciliation. The goal is not to pretend failures cannot happen; it is to make repeated delivery converge on one business outcome.

Test the failure paths that matter

A happy-path test proves only that the integration works when every response arrives. Add tests that deliberately delay or drop responses after the remote operation, retry with the same key, retry with changed data, and deliver two copies concurrently. Verify both the external record and your local state.

Monitor more than HTTP status codes. Track idempotency-key conflicts, unknown outcomes after timeouts, reconciliation attempts, and work that remains in progress beyond its expected window. Give an operator a short explanation of the record, the attempted action, and the available next step. A human review queue is valuable when the system cannot establish whether a side effect occurred.

A practical rollout checklist

  • List every workflow step that creates, charges, sends, or otherwise changes data in another system.
  • Assign a stable operation identity before the first remote attempt.
  • Document how the target API handles repeated keys, conflicts, and unknown outcomes.
  • Persist request and result state in a durable location with a retention period that fits the workflow.
  • Reconcile timeouts before allowing a new create request.
  • Test concurrent duplicates and changed-payload reuse in a non-production environment.
  • Route ambiguous cases to a person with enough context to decide safely.

Idempotency is a small concept with a substantial payoff in integration design: it turns a vague “try again” instruction into a defined contract. Start with the one workflow where a duplicate would be costly or confusing, document its operation identity, and test the recovery path before extending the pattern.

Next step: Schedule a short consultation to identify the next useful improvement.