cartalyst/resource-watcher
Resource Watcher lets Laravel apps monitor files and other resources for changes, dispatching events when modifications are detected. It offers a simple watcher API with periodic checks, handy for cache busting, asset tracking, or reacting to config and template updates.
Architecture fit. This is an enablement dependency, not a product capability, and a TPM should scope it accordingly. Legitimate homes are developer tooling (watch-and-rebuild loops), operational hygiene (config/template drift detection, cache invalidation on edit), and internal automation around long-running workers. It has no place in a customer-facing request path. The correct framing for the roadmap is: this package is an implementation detail of a larger feature — if the feature can't be justified without the watcher, the feature is the value, not the watcher.
Integration feasibility. Composer-installable, BSD-2-Clause, tiny surface, optional Laravel service provider and facade. Legal and procurement friction is effectively zero, and the exit cost is low because the API is small enough to wrap and replace. The real feasibility question is environmental. The source evidence is contradictory on mechanism — the package description advertises polling with configurable check intervals, while the Laravel dev assessment points at the Linux inotify extension. Both are credible for a library of this vintage, and both are consistent with "framework-agnostic core plus an optional Laravel provider." A TPM should treat the mechanism as unresolved until verified in the spike, because the answer determines whether this runs on macOS/Windows dev machines, through Docker Desktop bind mounts, and in production containers.
Technical risk. High risk relative to low value:
fs.inotify.max_user_watches → a misleading ENOSPC), or, in the polling case, silent latency drift and load on busy filesystems. Recursive watching of vendor/ or node_modules degrades either design.Key questions.
src/, not the README.spatie/file-system-watcher (fswatch-based), yosymfony/resource-watcher (polling), or delegating watching to Vite/Node?Stack fit. Optional utility confined to the console layer or internal tooling of a Laravel monolith. Isolate it behind our own small contract (watch() / on() / start()) so no controller, job, or domain service ever imports the package namespace. The adapter is the product decision; the package is a swappable detail behind it. That single architectural rule converts a vendor-risk conversation into a routine refactor conversation.
Migration path. If replacing a bespoke watcher, land the package behind the interface first, run both implementations in parallel for a validation window, then retire the old path. If it is net-new capability, ship it as a dev-only Artisan command or sidecar, not a production dependency, and promote only after health checks and fallback behavior are proven. For the common modern-Laravel case — Vite already watching frontend assets — the honest migration is no migration: route watching to existing tooling and keep this package out of the stack.
Compatibility. Three verifications gate the decision, all run in the same container image used in production: composer constraints against the target PHP/Laravel runtime; php -m | grep inotify in local, CI, container, and prod (if inotify-backed); and host-OS parity, since a developer on a macOS bind mount may see events a Linux host emits, or vice versa. BSD-2-Clause is compatible with proprietary code, but still route it through internal dependency policy so it appears on the SBOM.
Sequencing.
vendor, node_modules, .git, storage/*) and debounce/coalesce configured from the start.Maintenance. Assume internal ownership from day one: pin the version, vendor or fork for patch access, and track PHP compatibility on our upgrade cadence. There is no upstream activity pattern to inherit. Treat "we own this" as a small recurring line item and a standing risk-register entry — a low-cost, low-signal bet is still a bet, and the register entry is what stops it becoming an unowned surprise.
Support. Community-only, and thin. Our team writes the runbook, the troubleshooting guide, and the escalation path. The support cost is not ticket volume; it is the first engineer who hits ENOSPC on a Friday afternoon with no searchable answer. Pre-write the sysctl remediation and the ignore-list guidance before the pilot, not after.
Scaling. Watchers are per-node and OS-bound; they do not scale horizontally. Each node watches only its own local resources, and there is no cluster-wide coordination story. Cost scales with watch breadth × poll frequency (polling) or with watch-descriptor count (inotify). Keep the watched set deliberately narrow and never point it at vendor/ or a large asset tree. Any feature that implies cluster-wide "react to any file change anywhere" needs a different design entirely — a queue, object-storage events, or a config service — not this package.
Failure modes. Missed events through Docker Desktop bind mounts; silent watcher death with no supervisor noticing; inotify exhaustion surfaced as ENOSPC; permission errors; atomic saves arriving as delete+create; editor noise (.swp, ~, .git/index.lock); handler storms from missing debounce; and feedback loops where a log written into a watched directory re-triggers the watcher. Each needs an ignore rule, a debounce, a health check, or an accepted-and-documented limitation. An undocumented failure mode is an outage waiting for an owner.
Ramp-up. The API is trivial; the operational model is not. The learning curve is OS-level file watching — atomic saves, descriptor limits, bind-mount semantics, polling trade-offs — not library usage. Budget a short spike, document the chosen mechanism and why, and name an owner before anything reaches production. For a TPM, the ramp-up deliverable is a one-page decision record: what we watch, why, on which OS, with which fallback, what the CPU/latency budget is, and who is on the hook when it goes quiet.
How can I help you explore Laravel packages today?