yriveiro/php-fslock
A lightweight PHP library for managing file locks. It wraps flock() to acquire shared or exclusive locks, supports blocking and non-blocking modes, and provides simple lock release, helping coordinate concurrent processes and prevent race conditions.
Architecture fit: Unchanged in principle: yriveiro/php-fslock remains a process-level mutual exclusion primitive built on PHP’s flock, and it only coordinates processes that share a host and a filesystem view. Suitable for scheduled commands, CLI maintenance tasks, local exports, and single-node queue workers; unsuitable for multi-node workers, Kubernetes replicas, autoscaled queues, or cross-region coordination. The 3.0.0 release strengthens the fit for single-host use in one meaningful way: the new constructor parameter to configure where lock files are stored lets a team pin locks to a known path (tmpfs, a mounted volume, an app-owned directory) instead of accepting an implicit default. That improves predictability in containerized deployments but does not change the fundamental host-local boundary.
Integration feasibility: Still not Laravel-native, with no service provider, facade, config file, or framework integration; wrapping behind an internal LockService interface remains the recommended pattern. Two changes affect feasibility. First, the minimum PHP version is now declared as 7.x, which makes the compatibility statement more explicit than before but still does not confirm PHP 8.x support — a material gap given most Laravel estates run 8.1+. Second, explicit return type declarations modernize the API surface but introduce a subtle constraint: any application or vendor subclass overriding these methods must now match the declared signatures or it will fatal. The removal of destroy() is a breaking change and requires a usage audit before upgrading.
Technical risk: High for critical-path use, moderately reduced for approved host-local use. Positives: explicit return types and a declared PHP floor reduce ambiguity, and configurable lock storage removes a real operational unknown. Negatives: the removal of destroy() is a hard breaking change with no stated deprecation path in the release notes; the package remains a low-visibility, low-adoption dependency with an unclear maintenance cadence; flock remains advisory and filesystem-dependent, with unreliable behavior on NFS and some overlay/container storage drivers; and blocking acquisition without a proven bounded timeout still risks hung workers. The new lock-path parameter introduces a new class of risk: if two processes on the same host resolve different lock directories, they will silently fail to exclude each other. That is a correctness bug, not a bug report — nothing will error.
Key questions:
destroy() removal — was it deprecated in 2.x, and what replaces its cleanup role?Stack fit: Use only as a same-host coordination mechanism inside Laravel console commands, scheduled jobs, and local scripts. Do not use it as the primary lock for horizontally scaled queue workers. For distributed needs, prefer Laravel cache locks backed by Redis or database atomic locks. The configurable lock directory makes the package more viable for single-host container workloads provided the path is explicitly set to a location with reliable flock semantics — ideally an app-controlled local directory or tmpfs, not a network mount.
Migration path: Treat 3.0.0 as a breaking upgrade, not a patch. First, audit the codebase for destroy() usage; if any exists, either stay on the 2.x line or refactor cleanup expectations before upgrading. Second, audit any subclass or test double that overrides the affected methods, since the new return type declarations will enforce signature compatibility. Third, set the lock storage path explicitly per environment rather than relying on the default. Then run the same bounded pilot as before: one low-risk scheduled command, behind an application-owned lock interface, compared against Laravel’s built-in lock APIs. If the pilot is stable, extend to similar single-host tasks; if distributed coordination is needed, swap the adapter for Redis/database locking without changing call sites.
Compatibility: Verify PHP 8.x behavior empirically even though the release declares only a 7.x floor; verify Composer constraints; verify filesystem behavior for the configured lock directory under containers, mounted volumes, and concurrent CLI execution; verify that the removed destroy() method is not referenced anywhere in application or shared-library code; and verify that no subclass or mock breaks against the new return type declarations. If compatibility fails, vendor or fork the small implementation rather than depending on an unmaintained release.
Sequencing:
destroy() usage and for any subclassing or mocking of the lock class; decide upgrade versus stay on 2.x.php-fslock 3.x adapter for approved host-local cases.Maintenance: Low code surface but elevated ownership burden. The package is effectively a single-maintainer, low-adoption dependency; the team must track PHP compatibility, security advisories, and filesystem assumptions. The 3.0.0 release demonstrates the package can still ship breaking changes without a documented deprecation path, so dependency pinning is mandatory and an internal fork should be budgeted.
Support: Community support remains minimal. Internal documentation must now cover, in addition to the previous material, the canonical lock directory per environment and the fact that a mismatched path silently disables mutual exclusion. Documentation must also state the post-destroy() cleanup story: lock files are released on process exit but persist on disk, and operators can no longer clear state through the library itself. Avoid making this a hidden dependency in shared libraries.
Scaling: Scales only within a single host and filesystem boundary; it does not coordinate across pods, nodes, or regions. The configurable storage path helps direct lock churn to an appropriate volume, but high lock volume still creates file noise, and container restarts or rescheduling invalidate any assumption about shared paths persisting.
Failure modes: Blocking without timeout can hang workers. Newly prominent: a lock directory misconfiguration or environment drift causes silent non-exclusion — two processes both "acquire" and proceed with no error. NFS and overlay filesystems can produce unreliable locking. Permission or disk-full conditions can block acquisition. Stale lock files persist by design and, with destroy() removed, there is no in-library cleanup path, which will confuse operators. Process crashes generally release the lock but leave files behind. Monitor acquisition failures, wait duration, timeouts, command overlap, and the resolved lock path per process.
Ramp-up: Developer ramp-up is low because flock is simple; operational ramp-up is moderate and slightly increased by 3.0.0. Teams must understand advisory locking, same-host limits, the breaking destroy() change, and the fact that lock-path consistency is now a deployment invariant. Provide examples, a standard wrapper, a documented default lock directory, and a clear rule: host-local scheduled task only, never distributed worker coordination without a replacement.
How can I help you explore Laravel packages today?