---
title: "Make each change happen exactly once · Agent Wranglers"
url: https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/race-conditions
updated: 2026-10-20
licence: "All rights reserved"
---

# Make each change happen exactly once

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Abuse and limits](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits)
- Rule: Changes to money, stock and single-use items must happen once, even when the same request arrives twice at the same moment.
- 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).
- Check: Send the same coupon or withdrawal request 10 times at once with a test account. Only one succeeds, and the balance is right.

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
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers security testing playbook: https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/race-conditions`.

- Previous: [Work out every amount on the server](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/server-side-business-rules)
- Next: [Cap the size of every request and answer](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/resource-limits)
- [Abuse and limits](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits)
