Idempotency & Consistency: Why Your Payments Can't Duplicate
- WAU Marketing

- a few seconds ago
- 5 min read
Your payments' reliability isn't an assumption—it's a feature you design. If nobody designed it on purpose, what you have isn't a reliable core; it's one that simply hasn't failed in front of you yet.
There's a comfortable belief in many institutions: "payments just work." They go out, they arrive, they reconcile. Until one day a customer complains they were charged twice, or that their transfer "got lost" and reappeared hours later. That's when it becomes clear that reliability was never free. Behind every payment that doesn't duplicate sit two technical disciplines almost no one names in a business meeting—yet they decide whether your core is trustworthy or merely lucky: idempotency and transactional consistency.
The problem starts with something as dumb as the network
The network is unreliable, and that's not an opinion: it's the premise serious payment systems are designed around. Stripe's engineering team describes it with three failure scenarios any integration faces: the initial connection can fail; the call can drop mid-operation, leaving the work "in limbo"; or the operation can succeed on the server, but the connection breaks before it can tell the client, as Stripe explains in its engineering article on idempotency.
The third case is the dangerous one. Your banking app sends "charge $5,000," the charge did happen in the core, but the client never got the confirmation. What does almost any well-meaning system do? It retries. And there's your double charge. The problem, in Stripe's words, is that "the success of the operation is ambiguous from the perspective of the client, and it doesn't know whether retrying the operation is safe."
Idempotency: making retries safe
Idempotency is the property that makes repeating an operation produce the same result as running it once. In payments, this is implemented with an idempotency key: a unique identifier the client generates and sends with the request, so the server recognizes a retry for what it is—the same payment—not a new one.
The mechanism is elegant in its simplicity. Stripe saves the status code and body of the first response for each key; any later request with the same key returns exactly that result, even if it was an error, per its official API reference. That same documentation recommends using v4 UUIDs as keys, sets a 24-hour expiration, and—critically—the idempotency layer compares incoming parameters against the original request and errors out if they don't match, to keep a key from being accidentally reused on a different payment.
Translated to the business: the idempotency key is the difference between "the customer tapped pay three times because the app froze" and "a single charge was processed." It's not an engineering luxury; it's the minimum condition for retries—which will happen—to cost your institution neither money nor trust.
Consistency: making the data add up, always
Idempotency prevents the double charge. Transactional consistency solves a twin problem: a payment left half-done. A money movement is almost never a single write; it's several—debit one account, credit another, record the fee, notify. If the system crashes right in the middle, you can't keep the debit done and the credit pending. All or nothing.
In a classic monolithic core, the database solved this with ACID transactions. But modern architectures are distributed: multiple services, multiple databases. Enter the saga pattern, which architect Chris Richardson defines as "a sequence of local transactions," where each updates its database and triggers the next; and if one fails because of a business rule, "the saga executes a series of compensating transactions that undo the changes" of the preceding ones, per microservices.io. In other words: if the credit fails, the debit is compensated. The system returns to a coherent state instead of being torn in half.
The "exactly-once" almost nobody gets for free
Here's an uncomfortable truth the industry tends to gloss over: "exactly-once" (processing each message exactly one time) is extremely hard and expensive to guarantee in distributed systems. Most message brokers—Kafka, RabbitMQ, SQS—deliver at least once, meaning your system will receive duplicate messages. Real exactly-once doesn't come from the infrastructure; it's built by making consumers idempotent. Without that discipline, a saga that retries will "charge a card twice, ship a parcel twice, and refund a customer who already got a refund." Reliability, again, is something you design.
Why this got urgent: instant payments don't forgive
It used to be that a duplicate charge got caught in the overnight reconciliation and reversed before the customer ever noticed. That safety net is gone with instant payments. In Mexico, SPEI lets you "make electronic payments in a matter of seconds" and, via mobile banking, runs "24 hours, every day of the year," per Banco de México. And the decisive part: under the Circular 14/2017 framework, once a payment is accepted at Banxico's authorization point, it is irreversible.
Brazil moves the same way with Pix, where a transfer is practically irreversible once confirmed; the Central Bank had to create a Special Refund Mechanism (MED) letting fraud victims file claims up to 80 days later—precisely because the system doesn't allow "undoing" a payment the way it used to, as CommerceGate reported. When money moves in seconds and can't be reversed, a double charge is no longer a ledger entry you fix tomorrow: it's real cash that left, and your institution has to chase it.
Not theory: it happens to banks
This isn't a hypothetical. In March 2022, TSB—one of the UK's major banks—suffered a technical glitch that duplicated outgoing payments for thousands of customers, pushing some into overdraft overnight; the bank had to automatically reverse all the duplicate charges the next day and absorb the costs, as MoneySavingExpert reported. A bank with five million customers, duplicating payments because of a process failure. Idempotency and consistency aren't engineers' paranoia: they're what separates "minor incident" from "front-page news and thousands of furious customers."
How we see it at WAU
At WAU we treat reliability as what it is: a feature designed into the core from day one, not an assumption you pray for. We build idempotent payments—with keys that make any retry safe—consistent transactions—where a movement is all or nothing, with compensation when something fails—and consumers that tolerate duplicates without charging twice. This ties directly to two things we write about often in this blog: real-time reconciliation, which stops being a rescue net and becomes a live control, and instant payments, where there's no room to undo.
If your payments "just work" but nobody can explain what happens when the network drops mid-transaction, you don't have a reliable core: you have one that hasn't failed you in public yet. We help you make it reliable—by design. 👉 Book a conversation with our team.

.webp)



Comments