Reading this documentation https://docs.djangoproject.com/en/4.0/topics/db/transactions/#django.db.transaction.on_commit This is the use case for on_commit with transaction.atomic(): # Outer atomic, start a new transaction transaction.on_commit(foo) # Do things... with transaction.atomic(): # Inner atomic block, create a savepoint transaction.on_commit(bar) # Do more things... # foo() and then bar() will be called when leaving the outermost block But why not just write the code like normal without on_commit hooks? Like this: with transaction.atomic(): # Outer atomic, start a new transaction # Do things... with transaction.atomic(): # Inner atomic block, create a savepoint # Do more things... foo() bar() # foo() and then bar() will be called when leaving the outermost block It's easier to read since it doesn't require more knowledge of the Django APIs and the statements are put in the order of when they are executed. It's easier to test since you don't have to use any special test classes for Django. So what is the use-case for the on_commit hook? Continue reading...