
Send a publication notice only after the record it describes has committed. Otherwise, a user can receive a link to a listing that never became public. In Django, the database change and the follow-up notification have related but distinct success conditions.
Django's transaction documentation provides on_commit callbacks for actions that should follow a successful commit. It also explains that these callbacks are not part of the original transaction: a later callback failure does not roll the saved record back.
Name the durable change
For a directory, the durable change might be “this reviewed submission is published under this canonical slug.” The email or in-app notice communicates that state; it does not create it.
PublishYourSaaS, declared in the Django collection, describes a curated product directory. It is a useful workflow reference, not evidence of its internal transaction design.
In your implementation, write down the rows and relationships that must change together. Include the audit record or publication timestamp if the business contract requires them.
Keep external effects out of an uncommitted promise
A notification sent before commit may survive even when the database work rolls back. Trying to “undo” the email afterward is not a dependable recovery strategy.
For a noncritical follow-up, registering it after commit avoids describing a change that never happened. Test the rollback path explicitly: no success notice should be produced for an operation that failed before its durable state existed.
Keep callback behavior visible in tests. A test framework's transaction handling can affect when callbacks run, so use the appropriate testing support rather than assuming a callback was exercised.
Decide whether the follow-up must survive interruption
Running something after commit does not automatically make it durable across process failure. If delivery matters, record the pending follow-up as part of an appropriate durable workflow and let a worker retry it.
Tie that work to a stable operation identifier. Repeated processing should not produce several publication notices for the same transition.
This design question follows the consequence of losing the action. An optional analytic event and a required customer notice may deserve different recovery guarantees.
Separate publication failure from delivery failure
If the record is published but the message provider is unavailable, preserve the published state and show the delivery problem to operators. Do not casually revert public data just because a secondary service failed.
Conversely, a successful provider response should not override a failed publication decision. Each subsystem needs an authoritative status.
Keep user-facing messages precise. “Your submission is published; confirmation delivery is delayed” is different from claiming the entire operation failed.
Verify the boundary with controlled cases
In an isolated environment, test a successful commit, a forced rollback, a follow-up exception and a repeated worker attempt. Use a stub message destination so the test cannot contact real users.
Inspect the database, pending work and recorded notices together. The counts and states should explain one coherent outcome.
The companion Django admin workflow guide examines how an operator initiates the transition. For performance after correctness is established, use the existing Django PageSpeed guide.


