November 19, 2025

Laravel Tip: Dispatch Jobs After Your DB Transaction Commits

Tips
Laravel Tip: Dispatch Jobs After Your DB Transaction Commits

If you dispatch a queued job inside a database transaction, there’s a sneaky problem:

The job may run before your database changes are actually committed.

Meaning the job could query data that doesn’t exist yet… Or worse, fail because the record it depends on hasn’t been saved.

Laravel has your back with a simple fix:

Use afterCommit() to guarantee the job runs only after the DB transaction completes.


Perfect Example

Let’s say you're creating an order and sending a confirmation email:

Wrong (job might run before the order is saved)

DB::transaction(function () { $order = Order::create([...]); SendOrderEmail::dispatch($order); });

This job may run too early (dangerous territory).


Right Way (dispatch after commit)

DB::transaction(function () { $order = Order::create([...]); SendOrderEmail::dispatch($order)->afterCommit(); });

Boom. Now the job will only fire when the transaction is fully committed.

Safe. Predictable. Zero race conditions.


You Can Also Enable It at Job Level

If you always want this behavior for a specific job class:

class SendOrderEmail implements ShouldQueue { public $afterCommit = true; public function handle() { // ... } }

Now you don’t need to call ->afterCommit() each time.


When Should You Use afterCommit()?

Use it anytime your job:

  • depends on the newly created/updated record
  • reads the database inside handle()
  • triggers external services using that data
  • relies on IDs, relationships, or timestamps from the transaction

Examples:

  • Sending emails after user registration
  • Syncing an order with an external API
  • Creating invoices
  • Indexing records into Meilisearch/Algolia
  • Dispatching follow-up jobs
  • Updating statistics or analytics

Basically: if the job touches the DB record, then use it.


Summary

  • Jobs dispatched inside transactions can run too early
  • Use ->afterCommit() to avoid race conditions
  • Or set $afterCommit = true on the job class
  • This ensures clean, predictable, safe job execution
  • Essential for emails, APIs, search indexing, analytics, and more

Did you find this article helpful? Share it!