Two orders, one balance. That is the bug class an exchange has to design out before it has a single real user.
The naive flow reads like it works: check the user's free balance, accept the order, put it on the book, settle on match. It survives testing because a test client places orders one at a time.
In production two requests land in the same millisecond, read the same free balance, and both pass the check.
What fixed it for us was moving the truth out of the order row. Placing an order is a transfer from available to reserved, in one transaction, against a locked balance row, not a write to the book. The book only receives the order if the reservation succeeded. Cancels and partial fills release the exact remainder that was held, never a recomputed number.
The same rule applies to custodial withdrawals: a pending withdrawal is reserved funds, not a row with a status. If it only exists as a status, a second withdrawal request will be authorised against money that is already leaving.
So the test that matters is not whether a user can place an order. You want to know whether two concurrent requests can both succeed when only one should.
If a balance check and the action it authorises still live in two separate statements somewhere in your system, that is probably where this shows up.