---
title: "Take locks in one written order · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/concurrency/lock-order
id: ARC-80
level: Recommended
updated: 2026-10-22
tokens: 995
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Take locks in one written order

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Concurrency](https://agentwranglers.se/playbook/architecture/concurrency.md).

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

- ID: ARC-80
- Level: Recommended
- Chapter: [Concurrency](https://agentwranglers.se/playbook/architecture/concurrency.md)
- Rule: Write down which lock guards which data. When code needs more than one lock, it takes them in one fixed order, such as by ascending ID.
- Check: A stress test runs 1,000 transfers in both directions between two accounts at once. It finishes within 10 seconds and the total balance is unchanged. The database reports 0 deadlocks during the test.
- How: Two transfers between the same two accounts in opposite directions each take one lock and wait forever for the other. Taking locks in one global order makes that impossible. The same holds for database rows, so lock rows with `SELECT ... FOR UPDATE` sorted by ID. Prefer one lock, or none, as [Guard state that concurrent code shares](https://agentwranglers.se/playbook/architecture/coupling/guard-shared-state.md) says. Prefer a conditional write when conflicts are rare, as [Make conditional writes](https://agentwranglers.se/playbook/data/transactions-and-concurrency/conditional-writes.md) says. Locks across servers follow [Keep locks and counters in a shared store](https://agentwranglers.se/playbook/scaling/stateless-app-servers/shared-locks-and-counters.md). Put the lock map in a comment above the lock fields, since the code cannot show it.

## 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.

### Go example

```go
func (b *Bank) Transfer(from, to *Account, amount Cents) error {
	first, second := from, to
	if to.ID < from.ID {
		first, second = to, from
	}
	first.mu.Lock()
	defer first.mu.Unlock()
	second.mu.Lock()
	defer second.mu.Unlock()
	return moveFunds(from, to, amount)
}
```

### Python example

```python
def transfer(conn, from_id: int, to_id: int, amount: int) -> None:
    with conn.transaction():
        conn.execute(
            "SELECT id FROM accounts WHERE id = ANY(%s) ORDER BY id FOR UPDATE",
            ([from_id, to_id],),
        )
        conn.execute("UPDATE accounts SET balance = balance - %s WHERE id = %s", (amount, from_id))
        conn.execute("UPDATE accounts SET balance = balance + %s WHERE id = %s", (amount, to_id))
```

## Sources

- [CWE-833 Deadlock](https://cwe.mitre.org/data/definitions/833.html)

## Related rules

- ARC-40 [Guard state that concurrent code shares](https://agentwranglers.se/playbook/architecture/coupling/guard-shared-state.md) in Clean code and architecture
- DAT-16 [Make conditional writes](https://agentwranglers.se/playbook/data/transactions-and-concurrency/conditional-writes.md) in Data and databases
- SCL-8 [Keep locks and counters in a shared store](https://agentwranglers.se/playbook/scaling/stateless-app-servers/shared-locks-and-counters.md) in Scaling

**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/architecture/concurrency/lock-order">Agent Wranglers clean code and architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Start tasks only inside a scope that waits for them](https://agentwranglers.se/playbook/architecture/concurrency/structured-concurrency.md)
- Next: [Never hold a lock while waiting on the network](https://agentwranglers.se/playbook/architecture/concurrency/no-lock-across-io.md)
- [Concurrency](https://agentwranglers.se/playbook/architecture/concurrency.md)
