Laravel interview question · Most asked
How do you protect an endpoint against race conditions in Laravel, for example two users buying the last item?
Summary
Make the check and the write atomic: a conditional update (update ... where stock > 0), a row lock inside a transaction (lockForUpdate()), or a distributed lock (Cache::lock) for logic spanning several resources. Validation alone cannot prevent it.
Longer Answer
The naive version (read stock, check it, decrement) lets two requests read stock = 1 and both succeed. Options:
- Atomic conditional update:
Product::whereKey($id)->where('stock', '>', 0)->decrement('stock')returns the number of affected rows; 0 means sold out. Simple and fast. - Pessimistic lock: inside
DB::transaction,Product::lockForUpdate()->find($id), then check and update. Other transactions wait for the lock. - Optimistic locking: a
versioncolumn; updatewhere version = ?and retry on conflict. - Cache locks for cross-resource critical sections, keeping the database constraint as the final guarantee.
Key Points
- Read-check-write races without atomicity.
- Conditional update is simplest.
lockForUpdate()inside a transaction.- Optimistic locking with a version column.
Deep dive: Transactions, Locking & Concurrency in Code
More most-asked Laravel questions
- How do you validate requests in Laravel? Why use Form Requests?
- Gates or policies: how does authorization work in Laravel?
- What is mass assignment, and how do $fillable and $guarded protect against it?
- How do database transactions work in Laravel, and what pitfalls should you know?
- 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?
- How do queues work in Laravel?