Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Do File Cache Psr 6 Laravel Package

jord-jd/do-file-cache-psr-6

PSR-6 cache adapter for DO File Cache, letting you use the PSR-6 caching interface with a simple file-based backend. Install via Composer: composer require jord-jd/do-file-cache-psr-6.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit This package is a thin adapter, not a cache backend. It wraps jord-jd/do-file-cache (a plain PHP filesystem cache written by the same author) behind Psr\Cache\CacheItemPoolInterface. That is the whole scope: roughly a CacheItemPoolInterface implementation delegating to a directory of serialized files on local disk. It is not a DigitalOcean product, does not touch Spaces/S3, and requires no cloud credentials — earlier internal notes in this repo that describe DO API keys and multi-region filesystem replication are incorrect and should be retracted before anyone plans against them.

The consequential architectural fact is that Laravel does not have a PSR-6 cache slot. Laravel's Cache facade is built on Illuminate\Contracts\Cache\Store (with TaggableStore for tags), and Laravel's PSR-16 alignment comes via Illuminate\Contracts\Cache\Repository. There is no 'driver' => 'psr6' in config/cache.php, so the configuration snippets floating around in prior assessments will not boot. Realistically there are only two integration shapes:

  1. Consume the pool directly: bind CacheItemPoolInterface in the container and write new code against PSR-6. No Cache:: facade, no Cache::remember, no tags, no locks.
  2. Write a bridge: a ~100–200 LOC Store implementation (or a wrapper around symfony/cache's PSR-6→PSR-16 adapter) to make the pool usable from Cache::store('x'). That bridge is our code, our tests, and our maintenance burden — it is not in the package.

So the honest framing for the roadmap is: this package is a 200-line convenience, and the integration cost is the bridge plus the operational work of running a file cache. It only makes sense if we have a concrete, already-committed reason to be on DO File Cache.

Integration feasibility Install is trivial (composer require), but that is the least interesting part. Feasibility hinges on four verifications we have not done:

  • PSR version constraint. psr/cache 1.x has no return types; 2.0/3.0 added them. An adapter written against 1.x will not satisfy CacheItemPoolInterface under 2/3. Whether this package is installable alongside our current dependency graph is a composer why-not check, not an opinion. Given the last two releases were a namespace move (v3.0.0, breaking) and a badge fix (v3.0.1, docs-only), the constraint may not have moved with the ecosystem.
  • PHP version support. No CI signal we can trust: the README points at Travis CI, a service effectively dead since 2021. Assume untested on current PHP.
  • Laravel version drift. Zero dependents and 8 stars means nobody is filing issues when Laravel bumps its cache internals. We are the only integration test.
  • LGPL-3.0. This is a policy question before it is a technical one. Many enterprises disallow LGPL by default in application dependencies; others accept it if the library is unmodified and Composer-installed. Legal review is a gate, and it should run in parallel with the spike, not after.

Technical risk Ranked, with the ones that actually kill the project first:

  1. Single-host cache coherence. A filesystem cache is per-machine. On N app servers we get N independent caches: N× miss rate, divergent reads for the same key, and invalidation that only clears the host that served the request. If our target deployment is horizontally scaled (it usually is), this package is unsuitable as a primary cache, full stop. Shared-NFS is a known-bad workaround — file locking semantics on NFS are unreliable and the failure mode is silent corruption or hangs.
  2. Missing cache semantics. No tags, no atomic increment/decrement guarantees, no Cache::lock(). If any existing feature depends on Cache::tags() or atomic counters, it cannot move.
  3. Supply chain / bus factor. One maintainer, 8 stars, 0 dependents, releases that are documentation-only. Treat it as unmaintained-by-default: if it breaks, we fork it. That is acceptable for a small adapter, unacceptable for anything we cannot read in an afternoon.
  4. Thundering herd. PSR-6 has no lock semantics; a popular key expiring under concurrency means concurrent regeneration, each writing the same file. Laravel's remember() has the same class of problem, but Redis gives us an escape hatch via locks — a file cache does not.
  5. Vendor lock-in is inverted here. The lock-in risk is not to DigitalOcean; it is to a bespoke filesystem format with an author-specific key encoding. Exit cost is a cache flush, which is cheap — that part is genuinely low risk.

Key questions

  • Do we actually consume PSR-6 anywhere, or is this only ever reached through Cache::? If the latter, we are paying for a bridge to reach a file cache Laravel already ships (file driver, zero dependencies, tags unsupported in both cases).
  • What advantage does DO File Cache offer over Laravel's built-in file store, measurably? Without a benchmark, the answer is "none," and adoption fails the cost/benefit test.
  • How many app hosts, and is any cache key read on more than one?
  • Does any feature require tags, locks, or atomic increments?
  • Has Legal cleared LGPL-3.0 for application dependencies?
  • Is there an owner for the bridge code, or does this quietly become unowned infrastructure?

Integration Approach

Stack fit Only adopt if the answer to "why not Laravel's built-in file driver?" is concrete — e.g., we have an existing, deliberate commitment to DO File Cache, or a benchmark showing a material win for our workload. Even then, scope it narrowly: low-value, regenerable, read-mostly, single-host-tolerant caches such as rendered fragments, derived API payloads, or sitemaps. Never sessions, never queue state, never rate limiters, never anything where a stale read is a correctness bug.

Migration path

  1. Spike (1 sprint, timeboxed). One engineer, one branch: composer require, verify PSR constraint resolves against our lock file, write the minimal Store bridge, cache one real workload, measure hit rate and p95 latency against the file driver. Kill criteria stated up front — if the benchmark is not clearly better, we stop and close the ticket.
  2. Bridge if greenlit. Treat the Store adapter as first-party code: repo-owned, tested, documented, with a named owner. This is the real deliverable; the Composer package is an input to it.
  3. New code only. Do not retrofit. Any new feature needing a cache in the approved scope uses the new store; nothing existing is repointed.
  4. Retrofit candidate-by-candidate, each with a rollback flag. Cache is inherently reversible — a flush is the rollback — so the bar for trying a candidate is low, but the bar for making it the default store is high.
  5. Never as default. CACHE_DRIVER does not change. This is an opt-in named store.

Compatibility Pin the exact version (~3.0.1), pin psr/cache in the root composer.json if the adapter's constraint is loose, and add a CI job that runs the bridge against the lowest and highest PHP/Laravel versions we support. Assume no upstream support for future Laravel releases; budget a half-day per Laravel major to re-verify.

Sequencing Legal review and the PSR-constraint check run in week one, in parallel — both are cheap and either can kill it. Benchmark before bridge; bridge before any feature work. Infrastructure (directory creation, permissions, volume mount, disk-space alerting) lands before the first production write. Only after a quarter of clean operation is it eligible for a second workload.

Operational Impact

Maintenance Two things need owners: the Composer dependency (version pins, PHP/Laravel upgrade checks, watch for abandonment) and our bridge. Budget roughly one day per quarter for the pair, plus a fork-and-vendor contingency if upstream goes quiet — which, given the release history, is a "when," not an "if." Vendor it if we ship it: a composer.json pointing at a Git tag we control converts an external risk into an internal one we can actually fix.

Support Expect zero upstream support. No one is answering issues on an 8-star package; our on-call is the escalation path. The bridge's tests are therefore the documentation. Cache directories also need a documented lifecycle — creation, permissions, growth, purge — because "the disk filled up" is a boring, entirely predictable outage we should not have.

Scaling This is where the package is weakest and where the roadmap decision lives. It scales vertically and not at all horizontally. Concretely: on a single host it is fine; on two hosts it is a correctness problem for any shared key; on autoscaling groups with ephemeral filesystems it is worse than nothing, because every new instance starts cold and every terminated instance throws its cache away. If the twelve-month plan involves horizontal scaling — and it almost certainly does — then this is a stopgap with a scheduled obsolescence date, and the roadmap item should be written that way, with Redis or Memcached as the named successor and the same PSR-level interface so the swap is configuration, not refactoring.

Failure modes

  • Cold cache after deploy/restart — if the cache directory is inside the container image or an ephemeral volume, every deploy is a full cache miss and a latency spike. Requires a persistent volume; verify before rollout.
  • Silent staleness across hosts — no error, no alert, just divergent reads. Detect via per-host hit-rate dashboards; a divergence between hosts on the same key is the signal.
  • Disk exhaustion — TTL expiry is lazy; nothing guarantees eviction. Needs a size alert and a scheduled prune.
  • Permission failures — silent write failures degrade to a permanent miss, which looks like "cache doesn't work" rather than an incident. Log write failures explicitly.
  • Concurrent regeneration — expiry stampede on hot keys. Mitigate with jittered TTLs.
  • Corrupt/partial files — concurrent writes or an unclean shutdown can leave unreadable entries. The pool must treat unreadable entries as misses, not exceptions; verify that behaviour in the spike, because an uncaught unserialize error on a cache read is an outage.

Ramp-up Small. A mid-level Laravel engineer can read the entire adapter in an hour, and the bridge adds maybe half a day of onboarding. The cost is not learning the package — it is learning that the cache behaves differently from every other cache in the estate, which is why it must stay an explicitly named, narrowly scoped store with a written rationale in the ADR. Document the "why not file driver" answer in the ADR itself, or a future engineer will delete this as redundant — and they may well be right.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log