Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can you spot what’s wrong with code someone else wrote? Review this simplified Python-style money-transfer endpoint before scrolling to the findings. If it were a real pull request, what would you flag before approving it?

Try to identify all three issues first. The code is intentionally short; the challenge is to notice what its assumptions mean for money and concurrent requests.

Review the pull request

def transfer(sender, receiver, amount: float):
    if sender.balance < amount:
        raise ValueError("Insufficient funds")

    sender.balance -= amount
    receiver.balance += amount

Pause here and make your review notes. The three planted defects concern what values the endpoint accepts, how it represents money, and what can happen when transfers overlap.

Bug 1: The endpoint accepts zero and negative amounts

The code checks whether the sender has enough funds, but it never requires the transfer amount to be positive. A zero amount passes the check and makes no meaningful transfer. A negative amount is worse: subtracting it increases the sender’s balance, while adding it decreases the receiver’s balance. That reverses the intended direction of value.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Define the transfer’s valid input constraints and enforce them before changing either balance. For a simple positive-transfer rule, reject amounts less than or equal to zero. If the application also has minimums, maximums, or currency-specific increments, those rules need to be explicit too; the example does not establish them.

Bug 2: The amount is a binary floating-point number

The parameter annotation uses float. Binary floating-point cannot exactly represent some ordinary decimal fractions. The Python 3.11.17 documentation explains that decimal values such as 1.1 and 2.2 do not have exact binary floating-point representations, while Decimal can represent decimal values exactly and provides rounding controls: Python’s decimal documentation.

For financial values, choose a representation and policy that fit the application: a fixed-precision decimal type such as Decimal, or integer minor units such as cents for a currency that uses them. Changing the parameter type alone is not enough. The application must also define the currency, allowed scale, rounding behavior, input parsing, and compatible database representation.

Bug 3: The balance check and updates are not concurrency-safe

The endpoint reads the sender’s balance, checks it, and then updates two balances as separate-looking operations. If two requests run at the same time, both can see the same earlier balance and both pass the insufficient-funds check. Their combined transfers can exceed the sender’s available balance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a database-appropriate transaction strategy that makes the check and both account updates safe against competing transfers. A transaction wrapper alone does not guarantee this at every isolation level; the implementation must select a concrete mechanism for its database and isolation behavior.

For PostgreSQL, one option is to lock the relevant account rows with SELECT FOR UPDATE inside a transaction. PostgreSQL documents that these row locks prevent competing updates to the selected rows until the transaction ends: PostgreSQL 17: Explicit Locking. When locking both accounts, the implementation must also consider consistent lock ordering and how it handles deadlocks or other transaction failures. This PostgreSQL-specific technique is not a universal drop-in prescription for every database.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What to leave on the review

  • Require a valid positive amount before modifying balances.
  • Use a money representation and currency/rounding policy designed for the application.
  • Make the balance check and the sender-and-receiver updates safe when requests compete, using a database-specific transaction strategy.

Those are the three planted bugs in this example. It is a review exercise, not a complete production payment-system specification; the snippet does not establish other payment features or requirements.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.