Laravel interview question · Most asked
How do database transactions work in Laravel, and what pitfalls should you know?
Summary
DB::transaction(fn () => ...) commits if the closure returns and rolls back if it throws. It accepts a retry count for deadlocks. Side effects such as dispatching jobs or sending mail should wait until after the commit.
Longer Answer
DB::transaction($callback, attempts: 3) retries the whole closure when a deadlock occurs. Manual control is available with beginTransaction, commit and rollBack. Nested calls use savepoints.
Pitfalls:
- Jobs and events dispatched inside a transaction may run before the commit and not find the data (or find it rolled back). Use
->afterCommit()on the job or listener, or setafter_commiton the queue connection;DB::afterCommit(fn () => ...)does the same for arbitrary code. - External calls (HTTP, email) inside a transaction keep locks open and cannot be rolled back. Do them after the commit.
- Transactions do not prevent race conditions on their own: for read-then-write logic use
lockForUpdate()(orsharedLock()) inside the transaction, or an atomic conditional update. - Exceptions caught inside the closure do not roll back.
Code Example
DB::transaction(function () use ($orderId) {
$order = Order::whereKey($orderId)->lockForUpdate()->firstOrFail();
$order->markPaid();
ShipOrder::dispatch($order)->afterCommit();
}, attempts: 3);
Key Points
- Closure form commits or rolls back automatically; retries on deadlock.
- Dispatch jobs
afterCommit. - No external I/O inside transactions.
- Use
lockForUpdate()for read-modify-write.
Deep dive: Transactions, Locking & Concurrency in Code
Explanation
What interviewers look for
Awareness of the after-commit problem with queued jobs. It is a classic production bug.
Follow-up questions
- What isolation level does MySQL use by default?
- How would you prevent two workers from processing the same order?
More most-asked Laravel questions
- Gates or policies: how does authorization work in Laravel?
- How do queues work in Laravel?
- What is mass assignment, and how do $fillable and $guarded protect against it?
- How do you validate requests in Laravel? Why use Form Requests?
- Which Artisan commands would you run when deploying Laravel to production, and why?
- What is the service container, and how does dependency injection work in Laravel?
- What is the N+1 query problem in Eloquent and how do you prevent it?
- A Laravel endpoint is slow. How do you find and fix the cause?