[Django] #37369: on_commit should raise an error when no transaction is open

4 views
Skip to first unread message

Django

unread,
Sep 24, 2026, 6:59:11 AM (yesterday) Sep 24
to django-...@googlegroups.com
#37369: on_commit should raise an error when no transaction is open
-------------------------------------+-------------------------------------
Reporter: Charlie Denton | Type: New
| feature
Status: new | Component: Database
| layer (models, ORM)
Version: 6.1 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
When calling `on_commit` outside of a transaction, Django will execute the
callback immediately. This is a documented feature. See
https://docs.djangoproject.com/en/6.1/topics/db/transactions/#performing-
actions-after-commit

This leads to misleading code which looks as though it will defer work
when it will not. For example, it masks issues where `on_commit` is called
with a different `using=` argument to the transaction which is currently
open. (Either the transaction was opened on the wrong DB, or the callback
is waiting on the wrong database.)

Instead, it would make sense to adopt the behaviour of Django Subatomic's
`run_after_commit`, which raises an error when `on_commit` is called
outside of a transaction. After all, there will be no `COMMIT` when there
is no open transaction.

This idea was suggested when `on_commit` was introduced, but was seemingly
not addressed. See:

- https://github.com/django/django/pull/4593#issuecomment-98496218
- https://github.com/django/django/pull/4593#issuecomment-98762940

This has been discussed at Django on the Med 2026. The approach that was
suggested to me was:

Step 1:

- Change `on_commit` to raise an error when it is called without an open
transaction.
- Add a temporary setting to opt out of the new behaviour (and emit a
warning when `on_commit` is called with no transaction).

Step 2:
- Remove the opt-out setting.

To prevent a situation where code passes in tests but fails in production,
we should explicitly ignore the transaction created by the test suite when
checking if a transaction is open. Django Subatomic does this check using
a utility function: `in_transaction`. I believe that function would be a
useful addition to Django's API. See https://kraken-tech.github.io/django-
subatomic/v2.0.0/reference/django_subatomic/db/#django_subatomic.db.in_transaction
and https://github.com/django/new-features/issues/147.

The `in_transaction` API will enable developers who want to run the
callback immediately if there is no transaction:

{{{#!python
if in_transaction():
on_commit(my_callback)
else:
my_callback()
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/37369>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 24, 2026, 7:10:04 AM (yesterday) Sep 24
to django-...@googlegroups.com
#37369: on_commit should raise an error when no transaction is open
-------------------------------------+-------------------------------------
Reporter: Charlie Denton | Owner: (none)
Type: New feature | Status: new
Component: Database layer | Version: 6.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Lily):

* stage: Unreviewed => Accepted

--
Ticket URL: <https://code.djangoproject.com/ticket/37369#comment:1>

Django

unread,
Sep 24, 2026, 12:14:21 PM (yesterday) Sep 24
to django-...@googlegroups.com
#37369: on_commit should raise an error when no transaction is open
-------------------------------------+-------------------------------------
Reporter: Charlie Denton | Owner: Vishy
Type: New feature | Status: assigned
Component: Database layer | Version: 6.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Vishy):

* owner: (none) => Vishy
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/37369#comment:2>
Reply all
Reply to author
Forward
0 new messages