<-Back to Blog
fintechpaymentsapi-design

Idempotent Payment Endpoints: Lessons from Production

$author: Bio Lumbantoruan
$date: May 24, 2026

A customer clicks "Pay." The request times out. Their browser retries. Your server processes the same charge twice. The customer sees two deductions. Your support team gets a ticket. Your reconciliation report shows a discrepancy. All because the endpoint lacked idempotency.


I have debugged this scenario in production payment systems. The fix is not disabling retries. Retries are a fact of distributed systems: network timeouts, load balancer failovers, client-side connection drops all trigger them. The fix is designing endpoints that handle duplicate requests without creating duplicate side effects. That mechanism is the idempotency key.


What Idempotency Means in Payments


An operation is idempotent if executing it once produces the same result as executing it multiple times. In payment APIs, idempotency works by attaching a unique key to each request. The server remembers: "I processed a request with this key, here is the original response."


The Implementation Pattern


Three parts of this implementation matter: the cache check (look up the idempotency key before processing), the lock (prevent concurrent requests with the same key), and the TTL (keys expire after 24-48 hours).


Storage Options


Redis is ideal for high-throughput services: SET idempotency:{key} {response} EX 172800. A database table with a request_hash column works for lower traffic. The request hash catches the bug of a client reusing an idempotency key with a different request body.


When to Require Idempotency Keys


Any endpoint that creates a side effect involving money gets idempotency keys: charge, refund, transfer, and subscription creation endpoints.


Architecture is about trade-offs, not silver bullets. The idempotency key pattern trades a small amount of infrastructure complexity for a strong guarantee that retries do not become duplicate transactions.

The best way to get a project done faster is to start sooner.
— Robert C. Martin (Uncle Bob)