← Home
💬Real-life Scenario-based Interview QuestionsInterview QuestionsNEW
Must Know
Experience levelSenior · 5+ YOESenior / staff depth expected

A customer has ₹500 in their wallet. They initiate two payments of ₹500 simultaneously from two different devices. How would you prevent both transactions from succeeding?

PaymentsConcurrencyWalletDatabase

How I frame it

This is double-spend on a shared balance. Two devices = two independent HTTP requests with separate sessions — UI disable does nothing. Fix is server-side atomic debit on one wallet row.

Core solution

  • Pessimistic lock: SELECT balance FROM wallets WHERE user_id = ? FOR UPDATE inside transaction.
  • Conditional update: UPDATE wallets SET balance = balance - 500 WHERE user_id = ? AND balance >= 500 — second txn gets 0 rows updated → reject insufficient funds.
  • Append-only ledger: wallet_transactions with debit/credit rows; balance is cache or derived sum — audit trail for disputes.
  • Unique payment_id per intent: Each device creates distinct payment — both race; only one wins on balance. Retries of same intent use idempotency key.
Device A & B: POST /pay ₹500 (different payment_ids)
  Txn A: LOCK wallet → balance 500 → debit → 0 → COMMIT ✓
  Txn B: LOCK wallet (waits) → balance 0 → UPDATE WHERE balance>=500 → 0 rows → 402 ✗

Walkthrough

User has ₹500. Phone and laptop both tap Pay at same second. Both reach server. Serializable execution on wallet row: first commit wins, second sees zero balance. User gets one success and one "insufficient wallet balance" — never -₹500.

Weak answer

"Check balance in application code then deduct." Both threads read 500 before either writes — classic lost update without lock or conditional SQL.

Follow-up questions

Redis DECR on wallet balance for speed?

Only if DB reconciles async — risk on Redis loss. Financial wallets: DB is source of truth; Redis optional read cache invalidated on write.

Transfer between two users — deadlock?

Lock wallet rows in consistent order (lower user_id first) when debiting sender and crediting receiver in one txn.

Link to P2P transfer design?

Same ledger + lock pattern extended to two wallet rows in one transaction.