← back to projects

Betting Wallet Redesign

A wallet service where two bets placed at the same instant could both spend the same balance.

Results

What it did

Row lockcheck and debit in one transaction
1 writerper wallet at a time
Per walletdifferent accounts still run in parallel

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.

  1. Bet Request
  2. Wallet Lock
  3. Check & Debit
  4. Commit
  5. Settlement
  1. 01
    Bet RequestConcurrent stake requests arrive for the same account
  2. 02
    Wallet LockTransaction takes the row lock before reading the balance
  3. 03
    Check & DebitSufficient-funds check and write happen under the same lock
  4. 04
    CommitLock releases; the next bet reads the balance just written
  5. 05
    SettlementRejected 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

Read, then writebalance 100
  • idle · balance 100, nothing holds the row
Lock the wallet rowbalance 100
  • 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

C#/.NETSQL ServerTransactionsConcurrencyMicroservices

Working on something like this?