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.
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:
CacheItemPoolInterface in the container and write new code against PSR-6. No Cache:: facade, no Cache::remember, no tags, no locks.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/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.Technical risk Ranked, with the ones that actually kill the project first:
Cache::lock(). If any existing feature depends on Cache::tags() or atomic counters, it cannot move.remember() has the same class of problem, but Redis gives us an escape hatch via locks — a file cache does not.Key questions
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).file store, measurably? Without a benchmark, the answer is "none," and adoption fails the cost/benefit test.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
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.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.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.
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
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.
How can I help you explore Laravel packages today?