Djangocon EU: where did it all BEGIN;? Django’s transaction management - Charlie Denton & Sam Searles-Bryant¶
(One of my summaries of the 2026 Djangocon EU in Athens).
Transactions are an SQL concept. You “begin” a transaction, do a bunch of statements and at the end “commit” it. Only then does it actually show up in the database for other connections:
BEGIN;
INSERT ...;
UPDATE ...;
INSERT ...;
COMMIT;
If something goes wrong, you can abort it with “rollback”:
BEGIN;
INSERT ...;
UPDATE ...;
INSERT ...;
ROLLBACK;
The SQL default is to run in “autocommit” mode, so everything always updates the database immediately.
The history of Django’s transaction management:
<0.95 emulated sql’s autocommit by executing
COMMIT;after every save.0.95 introduced
with commit_on_success():, which would give you a context manager, at the end everything would be committed unless an error occurred. It did have a corner case: you couldn’t really nestcommit_on_success.1.6 introduced
with atomic():, mostly likecommit_on_success, but it introducedSAVEPOINT, allowing you to rollback a nested.atomic()to the savepoint that’s created when you enter a nested ‘atomic’ block.3.2 introduced
with atomic(durable=True):. If you had a nested atomic, a transaction you thought was committed might be rolled back by another ‘atomic’ wrapping the code. When you specifydurable=True, calling ‘atomic’ fails with an error, as it isn’t legal in this case.
In their own projects they sometimes wanted to have more explicit control. They
sometimes had a check like if assert not connection.in_atomic_block, but that didn’t
look nice. They split atomic() into separate transaction(), savepoint() and
durable() context managers. Nicely explicit.
The code is here: https://github.com/kraken-tech/django-subatomic
A big inspiration for them was a talk by Aymeric Augustin at the 2013 djangocon.eu. Here’s my summary of that talk.
Unrelated photo explanation: a cat I encountered in Athens on an evening stroll in the neighbourhood behind the hotel.