Betting Wallet Redesign
A wallet service where two bets placed at the same instant could both spend the same balance.
Results
What it did
The problem
Why it needed building
Under load, concurrent bets on one account raced each other. Each bet read the balance, checked it had enough, then wrote the new total — so two bets arriving together both read the same balance, both passed the check, and both debited it. The account drained twice and the platform paid out money that was never there. Money bugs do not degrade gracefully: every one of them has to be reconciled by hand afterwards.
The approach
How it works
Moved the check and the debit inside a single transaction that takes a lock on the wallet row before reading it. A second bet on the same wallet blocks until the first commits, then reads the balance the first one actually left behind — so the check can never run against a stale number. Bets on different wallets are untouched and still run fully in parallel.
- Bet Request
- Wallet Lock
- Check & Debit
- Commit
- Settlement
- 01Bet RequestConcurrent stake requests arrive for the same account
- 02Wallet LockTransaction takes the row lock before reading the balance
- 03Check & DebitSufficient-funds check and write happen under the same lock
- 04CommitLock releases; the next bet reads the balance just written
- 05SettlementRejected stakes return insufficient funds, never a partial debit
The trade-off
What it cost
Writes to a single wallet now serialize, so a hot account is a throughput ceiling no number of instances can raise. That was the right trade: concurrency on one wallet is worth very little, and a double-spend is unrecoverable once the payout leaves.
Live demo
Try it yourself
- idle · balance 100, nothing holds the row
- idle · balance 100, lock free
Two bets of 100 hit a balance of 100 at the same moment. The left lane is the bug; the right lane is the fix.
Tech stack
Built with
Working on something like this?