---
title: "Make each change happen exactly once · Agent Wranglers"
url: https://agentwranglers.se/playbook/application-security/limits-and-business-logic/race-conditions
id: APS-53
level: Required
risk: money
updated: 2026-10-27
build: a2a6bdfed830
tokens: 949
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Make each change happen exactly once

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Limits and business logic](https://agentwranglers.se/playbook/application-security/limits-and-business-logic.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: APS-53
- Level: Required
- Chapter: [Limits and business logic](https://agentwranglers.se/playbook/application-security/limits-and-business-logic.md)
- Rule: Changes to money, stock and single-use items must happen once, even when the same request arrives twice at the same moment.
- Check: On the test copy, send the same coupon or withdrawal request 10 times at once with a test account. Only one succeeds, and the balance changes by exactly one use.
- Risk: Money lost or taken twice
- How: Do the check and the change in one atomic database step, such as a conditional update or a unique constraint. Give payment requests an idempotency key, so a repeat returns the first result. Avoid reading a value, deciding, and writing it back in separate steps. For more depth, see [conditional writes](https://agentwranglers.se/playbook/data/transactions-and-concurrency/conditional-writes.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### SQL example

```sql
-- One step: the coupon is used only if it was still unused
UPDATE coupons SET used_by = :user WHERE code = :code AND used_by IS NULL;
-- 0 rows changed means someone else already used it
```

## Sources

- [OWASP WSTG on testing payment functionality](https://wstg.owasp.org/latest/4-Web_Application_Security_Testing/10-Business_Logic/10-Payment_Functionality/)
- [CWE-362 Race Condition](https://cwe.mitre.org/data/definitions/362.html)

## Related rules

- DAT-15 [Know your isolation level](https://agentwranglers.se/playbook/data/transactions-and-concurrency/isolation-levels.md) in Data and databases
- DAT-16 [Make conditional writes](https://agentwranglers.se/playbook/data/transactions-and-concurrency/conditional-writes.md) in Data and databases
- PAY-14 [Create each charge with an idempotency key](https://agentwranglers.se/playbook/payments/amounts-and-orders/idempotent-charge-creation.md) in Payments and billing
- PAY-15 [Keep one open payment per order](https://agentwranglers.se/playbook/payments/amounts-and-orders/one-open-payment-per-order.md) in Payments and billing
- ECM-7 [Decrement stock in one conditional update](https://agentwranglers.se/playbook/ecommerce/stock-and-reservations/atomic-stock-decrement.md) in E-commerce and fulfilment
- ECM-23 [Hand out each licence key once](https://agentwranglers.se/playbook/ecommerce/orders-and-fulfilment/licence-keys-once.md) in E-commerce and fulfilment
- ECM-37 [Limit each coupon per customer instead of per account](https://agentwranglers.se/playbook/ecommerce/promotions-and-claims/coupon-limits.md) in E-commerce and fulfilment

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/application-security/limits-and-business-logic/race-conditions">Agent Wranglers application security playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Work out every amount on the server](https://agentwranglers.se/playbook/application-security/limits-and-business-logic/server-side-business-rules.md)
- [Limits and business logic](https://agentwranglers.se/playbook/application-security/limits-and-business-logic.md)
