Concurrency fix 2: pessimistic locking with select_for_update()

Django Concurrency November 13, 2026 python

How do you use pessimistic locking with select_for_update() to prevent race conditions?

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# ======================================================================
# Q: How do you use pessimistic locking with select_for_update() to prevent race
# conditions?
# ======================================================================

from django.db import transaction

with transaction.atomic():
    account = Account.objects.select_for_update().get(pk=account_id)  # SELECT ... FOR UPDATE
    if account.balance < amount:
        raise InsufficientFunds()
    account.balance -= amount
    account.save(update_fields=['balance'])
    Ledger.objects.create(account=account, amount=-amount)
# the lock is released at COMMIT