pyaesoneaung/atomic-locks-middleware
Laravel middleware that prevents overlapping requests by wrapping routes in atomic cache locks. Guard critical endpoints from concurrent execution with configurable keys, wait times, and automatic release—no boilerplate needed.
Architecture fit. The package is a thin, idiomatic Laravel middleware that wraps Laravel's native atomic lock contract (Illuminate\Contracts\Cache\LockProvider). It occupies the correct horizontal seam in the request lifecycle — acquire before the controller/handler, release after the response or on exception — which means it composes with existing route groups, form requests, and exception handling rather than requiring application restructuring. For teams already running stateless app servers behind a shared Redis/Memcached/DynamoDB cache, this is architecturally aligned. It is not a queue, not a scheduler, and not a replacement for idempotency keys; it is request-level mutual exclusion.
Integration feasibility. Composer install, optional config publish, middleware registration, and per-route or per-group attachment. The only hard external dependency is a cache store that implements the lock provider interface — Redis, Memcached, DynamoDB, or database. file and array drivers technically support locks but are node-local and therefore wrong for any multi-instance deployment. Integration cost is measured in hours, not sprints, for a team that already understands Laravel middleware.
Technical risk. The code footprint is small; the blast radius is not. A middleware that serializes requests sits directly on the hot path and can convert a throughput problem into an availability incident. Specific risks:
maxmemory-policy set to allkeys-lru can evict a lock key mid-flight. Cluster/Sentinel failover can lose recent lock writes. The package cannot insulate you from this; your cache topology must be reviewed.Key questions to resolve before adoption.
terminate() paths?composer.json, and is there a CI matrix?Stack fit. Best fit is a Laravel 10/11/12 application on PHP 8.1+, horizontally scaled, backed by Redis (preferred) or DynamoDB. Poor fit for single-server deployments using the file cache, for apps without a shared cache tier, and for workloads where the serialized unit is a user session rather than a business entity.
Migration path. Two common entry points:
Cache::lock() calls scattered through controllers and jobs → this middleware centralizes acquisition/release and removes duplicated try/finally blocks. Low-risk, high-cleanup value.There is no data migration and no schema change. Rollback is removing the middleware alias from the route group.
Compatibility checks. Confirm the declared Laravel/PHP constraints against your composer.json before anything else, then confirm your cache store is a LockProvider and that Redis is not configured with a volatile eviction policy for the lock database. Use a dedicated Redis connection or logical database for locks if the cache is shared with session or page-cache traffic.
Sequencing.
Maintenance. The vendor surface is tiny — a handful of classes under MIT — which makes forking or vendoring into the application a genuinely viable de-risking move. The counterweight is a single maintainer and a young release history; assume the package may go unmaintained and plan to own the code. Pin the version explicitly and review the diff before every bump.
Support. Community issues only. No commercial backing, no SLA, no security disclosure process observed. For a component on the request hot path, treat internal ownership as mandatory: assign a named engineer, write an ADR, and add a fork-and-patch runbook.
Scaling. Throughput is bounded by lock granularity, not by the package. A per-entity key scales close to horizontally; a per-route or global key caps effective throughput at roughly 1 / handler_duration requests per second for that route, which is often catastrophic and always surprising. Lock acquisition adds one network round trip (~0.5–2ms to Redis) per request plus release; keep the lock scope as narrow as correctness allows. Watch for thundering-herd behavior when a popular key is released and many waiters contend simultaneously.
Failure modes.
noeviction policy for the lock store.Ramp-up. Mechanically trivial for any Laravel developer — a middleware alias and a route group. Conceptually it requires distributed-systems literacy that many application teams under-index on: at-most-one semantics, TTL-versus-latency budgeting, lock key scoping, and the difference between mutual exclusion and idempotency. Budget a half-day of design review for the first adoption and require a written key-design convention before the second route is protected. The package is a reasonable, low-cost option for narrow, well-understood serialization needs in a mature Laravel codebase; it is not a general-purpose concurrency solution and should not be adopted without an internal owner.
How can I help you explore Laravel packages today?