- How do I install and set up zaber-dev/laravel-lock?
- Install it with Composer using composer require zaber-dev/laravel-lock. Then publish the config with php artisan vendor:publish, which gives you a single config/locks.php file containing the default driver and event toggle. If you plan to use the database driver, run php artisan migrate to create the locks table. No service-provider overrides or framework patching are required.
- Which Laravel and PHP versions does laravel-lock support?
- The package states support for Laravel 11, 12 and 13+, along with PHP 8.2 or newer. It works with Redis, Memcached and a database-backed store. Because the Laravel 13+ target and the listed release date look unusual for current metadata, verify the actual tags on Packagist before pinning a version in production.
- How is laravel-lock different from Laravel's Cache::lock()?
- It is a thin, opinionated layer over Laravel's existing Cache::lock() primitive rather than a new locking runtime. The value it adds is standardized key derivation through Lock::for($action, $target), automatic owner detection, a HasLocks trait for Eloquent models, middleware, lifecycle events, and cleanup. You can adopt it in a single critical path and leave existing Cache::lock() call sites in place indefinitely.
- How do I attach a lock to an Eloquent model?
- Use the HasLocks trait on the model and acquire locks through the facade with the model as the target, for example Lock::for('billing_charge', $user). The package resolves polymorphic targets and derives a consistent key such as billing_charge:{user_id}, which codifies naming that otherwise drifts across teams. The same pattern works for webhooks, payouts and inventory records.
- Should I use the cache or database driver for distributed locks?
- Cache drivers such as Redis and Memcached are the natural fit when you already run a shared cache and want low-latency acquisition. The database driver adds persistence and is useful when you want lock records you can inspect, but it requires the locks table and a pruning schedule. Be aware that cache and database locking are not equivalent under contention, clock skew and connection loss, so verify the acquisition semantics in code before trusting them on payment or ledger paths.
- How do I protect a route with the lock middleware?
- Add the middleware to a route with parameters for action, TTL and optional driver, for example lock:billing_charge,60,redis. It is a one-line change and returns HTTP 429 automatically when the lock cannot be acquired, which suits webhook and payout endpoints. Because it silently imposes a per-request lock scope, validate the key derivation against real traffic before relying on it for concurrency control.
- Why is my lock still held, and when should I use forceRelease()?
- A lock normally clears when the owning process releases it or when its TTL expires, so a stuck lock usually means a crashed worker or a job that outlived the TTL. forceRelease() exists for that operational case and emits a LockForceReleased event. Treat it as a loaded gun: using it as a routine fix for slow jobs converts visible lock contention into silent double-writes.
- Does laravel-lock support lock refresh, heartbeats or fencing tokens?
- There is no visible lock extension or heartbeat API, so a fixed TTL means any critical section that can exceed it will silently lose exclusivity mid-execution. There are also no fencing tokens, so an expired lock cannot stop a stale writer from committing after a new holder starts. For payments, ledgers and inventory, enforce this at the data layer with version columns, idempotency keys and conditional updates. The block() helper only guarantees release, not extension.
- Do I need to schedule model:prune when using the database driver?
- Yes. The database driver stores lock rows in a table that must be cleaned up with a scheduled model:prune invocation. If that schedule is missing or misconfigured, the locks table grows unbounded and index contention degrades acquisition latency over time. Add the prune task in the same deployment that enables the database driver.
- Is zaber-dev/laravel-lock production ready, and what are the alternatives?
- It is a pre-traction package with a small star count, no dependents, MIT licensing, and documentation limited to the README and releases, so treat it as source-available code you may need to fork rather than a supported dependency. For simpler needs, Laravel's built-in Cache::lock() plus your own key conventions is the main alternative, and heavier workflow concerns belong in a dedicated queue or saga implementation. The package solves mutual exclusion only and is not a replacement for an outbox, workflow engine or exactly-once processing design.