Laravel Lock: Distributed Locks for Models &amp; Routes | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. [Laravel](https://www.msaied.com/public/articles?category=laravel)
6. /
7. Laravel Lock: Distributed Locks for Models and Routes

   [Laravel](https://www.msaied.com/public/articles?category=laravel) [Composer Pacakge](https://www.msaied.com/public/articles?category=composer-pacakge) 

 Laravel Lock: Distributed Locks for Models and Routes
======================================================

 Laravel Lock is a package by Md Mahedi Zaman Zaber that wraps distributed locking behind a fluent builder, a HasLocks model trait, and route middleware — backed by either cache or database storage.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 17 Aug 2026 · Updated 18 Aug 2026 · 4 min read

ShareCopy linkCopied

 ![Laravel Lock: Distributed Locks for Models and Routes](https://cdn.msaied.com/562/7649de72113e99332a9f7e25015f9397.png) 

  On this page +1. [What Is Laravel Lock?](#what-is-laravel-lock)
2. [Acquiring and Releasing Locks](#acquiring-and-releasing-locks)
3. [Model-Scoped Locks with HasLocks](#model-scoped-locks-with-haslocks)
4. [Route Middleware](#route-middleware)
5. [Cache vs. Database Storage](#cache-vs-database-storage)
6. [Installation](#installation)
7. [Key Takeaways](#key-takeaways)

 What Is Laravel Lock?
---------------------

Race conditions in queue workers are easy to overlook until a customer receives two identical shipments. Laravel's built-in `Cache::lock()` handles the primitive, but you still have to format the key, manage the owner token, and remember the `finally` block every time. [Laravel Lock](https://github.com/zaber-dev/laravel-lock), by Md Mahedi Zaman Zaber, wraps all of that behind a fluent builder, a model trait, and route middleware.

Acquiring and Releasing Locks
-----------------------------

The `Lock` facade accepts an action name and an optional target, then returns a pending lock you can configure before acquiring:

```php
use ZaberDev\Lock\Facades\Lock;

$lock = Lock::for('shipment_dispatch', $shipment)->ttl(120);

if ($lock->acquire()) {
    try {
        $carrier->dispatch($shipment);
    } finally {
        $lock->release();
    }
}

```

Each builder generates its own UUID owner token. A second `Lock::for(...)` instance carries a different token, so calling `release()` on it does nothing — preventing accidental cross-process releases. When the acquire and release happen in separate processes, set the token explicitly with `->owner('worker-7')`.

For a cleaner one-liner, `block()` acquires, runs the callback, and releases automatically:

```php
$manifest = Lock::for('shipment_dispatch', $shipment)
    ->block(function () use ($shipment, $carrier) {
        return $carrier->dispatch($shipment);
    });

```

If the lock is already held, `block()` throws `LockAcquisitionException` — which carries the `LockInfo` of the blocking lock — rather than silently skipping the work. Both `acquire()` and `block()` accept a wait duration so they retry before giving up:

```php
$lock->acquire(blockSeconds: 5);
Lock::for('stock_allocation', $warehouse)->block($callback, 60, 5);

```

Model-Scoped Locks with HasLocks
--------------------------------

Add the `HasLocks` trait to any Eloquent model and the lock target is derived automatically from the morph class and primary key:

```php
use ZaberDev\Lock\HasLocks;

class Shipment extends Model
{
    use HasLocks;
}

$shipment->lock('dispatch')->ttl(120)->acquire();
$shipment->isLocked('dispatch');
$shipment->forceReleaseLock('dispatch');

```

The generated key looks like `dispatch:App_Models_Shipment:42`. Register a morph map and you get the shorter alias. Non-model targets can implement the `Lockable` interface and return a custom identifier string.

Route Middleware
----------------

The package registers a `lock` middleware alias. Pass it an action name and a TTL in seconds:

```php
Route::post('/warehouse/reconcile', [ReconcileController::class, 'store'])
    ->middleware('lock:warehouse_reconcile,300');

```

To scope the lock to a specific route model binding, embed the parameter in the action name:

```php
Route::post('/shipments/{shipment}/dispatch', [ShipmentController::class, 'dispatch'])
    ->middleware('lock:shipment_dispatch:{shipment},60');

```

When the lock is already held, the middleware throws `LockAcquisitionException` before the controller runs. The exception code is 423, but you need to handle it explicitly to return the right HTTP status:

```php
$exceptions->render(function (LockAcquisitionException $e) {
    return response()->json([
        'message' => 'Already processing. Try again in a moment.',
        'retry_after' => $e->lockInfo?->remainingSeconds(),
    ], 429);
});

```

Cache vs. Database Storage
--------------------------

The default driver is set via `LOCK_DRIVER`. Switch per lock with `->using('database')`:

- **Cache driver** — uses `Cache::add()` for atomicity; fast and suitable for Redis or Memcached.
- **Database driver** — writes to a `locks` table with `lockForUpdate()` inside a transaction; survives cache flushes and supports Eloquent queries.

Expired rows are pruned via Laravel's `Prunable` trait. Schedule it daily:

```php
Schedule::command('model:prune', ['--model' => LockModel::class])->daily();

```

Three events fire when enabled: `LockAcquired`, `LockFailed`, and `LockReleased`. Listening for `LockFailed` surfaces which actions actually contend in production.

Installation
------------

Requires PHP 8.2+ and Laravel 11, 12, or 13:

```bash
composer require zaber-dev/laravel-lock
php artisan vendor:publish --tag=locks-config
php artisan vendor:publish --tag=locks-migrations
php artisan migrate

```

Key Takeaways
-------------

- Fluent builder with `acquire()`, `block()`, `refresh()`, and inspection helpers like `remainingSeconds()`.
- `HasLocks` trait auto-generates model-scoped lock keys using morph class and primary key.
- Route middleware protects endpoints or individual model routes without touching controller code.
- Two drivers: fast cache-backed locks or durable database locks that survive restarts.
- `LockAcquisitionException` carries `LockInfo` so callers know how long to wait before retrying.

---

Source: [Laravel Lock: Distributed Locks for Models and Routes — Laravel News](https://laravel-news.com/laravel-lock)

- [Laravel](https://www.msaied.com/public/articles?search=Laravel)
- [Distributed Locks](https://www.msaied.com/public/articles?search=Distributed%20Locks)
- [Composer Package](https://www.msaied.com/public/articles?search=Composer%20Package)
- [Race Conditions](https://www.msaied.com/public/articles?search=Race%20Conditions)
- [Queue Workers](https://www.msaied.com/public/articles?search=Queue%20Workers)

 Frequently asked questions 
---------------------------

  What is the difference between the cache and database drivers in Laravel Lock?The cache driver uses `Cache::add()` for atomicity and is faster, making it suitable for short-lived locks on Redis or Memcached. The database driver writes rows to a `locks` table using `lockForUpdate()` inside a transaction, so locks survive a cache flush or Redis restart and can be queried with Eloquent.

   How does the route middleware handle a request when a lock is already held?The `lock` middleware throws a `LockAcquisitionException` before the controller runs. The exception code is 423, but you must handle it explicitly in your exception handler to return the appropriate HTTP status to the client — for example, a 429 response with a `retry\_after` value from `$e-&gt;lockInfo-&gt;remainingSeconds()`.

   Can I use Laravel Lock with non-Eloquent targets?Yes. For targets that are not Eloquent models, implement the `Lockable` interface on your value object and return a custom identifier string from `getLockTargetIdentifier()`. That string becomes the second segment of the lock key.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleLerd: A Free, Open Source Laravel Herd Alternative for Linux and macOS](https://www.msaied.com/public/articles/lerd-a-free-open-source-laravel-herd-alternative-for-linux-and-macos) [Next articleLaravel Chores: Resumable, Checkpointed Data Operations for Large Datasets](https://www.msaied.com/public/articles/laravel-chores-resumable-checkpointed-data-operations-for-large-datasets)  

   On this page
-------------

1. [What Is Laravel Lock?](#what-is-laravel-lock)
2. [Acquiring and Releasing Locks](#acquiring-and-releasing-locks)
3. [Model-Scoped Locks with HasLocks](#model-scoped-locks-with-haslocks)
4. [Route Middleware](#route-middleware)
5. [Cache vs. Database Storage](#cache-vs-database-storage)
6. [Installation](#installation)
7. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
