transaction.atomic() bọc một khối code thành transaction theo nguyên tắc all or nothing. Bên trong raise exception → mọi INSERT/UPDATE/DELETE đã chạy trong khối đó được rollback hết.
Dùng khi nhiều bước nghiệp vụ phải nhất quán với nhau: tạo đơn hàng + trừ kho + ghi audit log. Hoặc khi dùng select_for_update() để khoá hàng chống race condition.
from django.db import transaction
with transaction.atomic():
order = Order.objects.create(...)
Stock.objects.filter(sku=sku).update(qty=F('qty') - 1)
AuditLog.objects.create(action='order.created', order=order)Nên đặt ở layer service, không phải view, để dễ test và tái sử dụng. Hoặc dán decorator @transaction.atomic lên function service.
Một cái sai rất phổ biến là gọi external API (HTTP, email, webhook) bên trong atomic — vừa chậm vừa dễ lỗi nửa chừng (mạng treo, response lâu). Cách đúng là transaction.on_commit(lambda: send_email(...)) — Django chỉ chạy callback đó sau khi transaction commit thành công.