News · New this week
UPI idempotency: how a double tap debits once
One payment, one transaction ID. Here is why a second tap or a retry on timeout doesn't take your money twice.
The interview question is simple. You pressed Pay twice, so how does the money leave the account only once? The short answer is that one payment carries one transaction ID, and every layer checks that ID before it acts.
The ID stays the same on retry
The PSP app creates the transaction ID when the payment starts. A second tap, or an automatic retry, sends that same ID again.
This is the part people get backwards. If a retry generated a new ID, the system would see a new payment and debit again. So the ID never changes across retries. One payment, one ID.
NPCI dedupes by ID
Think of a shopkeeper's ledger. If the same slip number comes in twice, he doesn't add a second entry. The ID is the slip number.
The NPCI switch works the same way. When the same ID arrives again, it doesn't create a new entry. It returns the old status for that payment. The app gets an answer, and nothing new is debited.
The bank checks too
The issuer bank also looks at the ID. It debits once and saves the state against that ID. So even if a repeat somehow got past the earlier step, the bank has a record that this payment is already done.
That gives you the full chain. The app makes the ID, NPCI dedupes on it, and the bank debits once and stores the state. Each layer is a separate guard on the same key.
Timeout means pending, not failed
Slow networks are where double taps come from. The app waits, hears nothing, and the user presses Pay again.
A timeout doesn't tell you the payment failed. It means pending. The status stays pending until you get success or failed. So the app doesn't guess. It asks for a status check using the same ID.
There's one more case. If the debit happened but the credit didn't, auto reversal brings the money back.
What to say in the interview
Keep it to a few points. The ID stays the same on retry, so a retry is safe. NPCI returns the old status for a repeated ID. The bank debits once and saves the state. A timeout is pending, and the app checks status with the same ID.
The same shape applies to your own payment API. The client creates the key once, reuses it on every retry, and the server returns the stored result for a key it has already seen. Try writing out how your API handles a repeated key, then check whether it returns the old state or creates a new record.


