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

Prefixed Cache Laravel Package

cache/prefixed-cache

Decorates any PSR-6 or PSR-16 cache so every key automatically carries a fixed prefix. PrefixedCachePool::create() also supports native tags, and prefixes are safely encoded before joining to keys.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. cache/prefixed-cache is a single-purpose decorator: it wraps a PSR-6 CacheItemPoolInterface and rewrites every key to prefix + key. Architecturally it is a clean, well-bounded seam — no global state, no framework coupling, composition over inheritance. The important caveat for a Laravel shop is that Laravel's cache layer is PSR-16-shaped, not PSR-6. Illuminate\Contracts\Cache\Repository (get/put/remember) is not a CacheItemPoolInterface, and CacheManager does not hand out PSR-6 pools. This package therefore does not "drop into" config/cache.php; it only helps if you already have PSR-6 pools in the process (e.g. php-cache/* adapters, symfony/cache PSR-6 adapters, or a third-party SDK that type-hints Psr\Cache\CacheItemPoolInterface). Any plan that assumes out-of-the-box Redis/Memcached support through Laravel's drivers is wrong and should be corrected before it reaches a roadmap.

Integration feasibility. Feasible in narrow, well-defined cases:

  • A vendor library or internal shared package type-hints PSR-6 and you need per-tenant/per-module key isolation.
  • You are consolidating several apps onto one Redis cluster and want namespacing at the pool level rather than sprinkling prefixes through call sites.
  • You want a migration seam where legacy raw-Redis code and new cache code coexist.

Not feasible as a general Laravel namespacing mechanism — Laravel already supports a per-store prefix in config/cache.php, applied by the cache manager. For the mainstream use case (one app, several stores, tenant-aware keys), the native prefix plus a small tenant-aware key builder is strictly simpler and adds no dependency.

Technical risk. Ranked, highest first:

Risk Assessment Mitigation
Reserved characters in PSR-6 keys PSR-6 reserves { } ( ) / \ @ : in keys. The README and internal pitches both use tenant_1:user_123 and acme:api:v1 as examples. On strict pools (Symfony adapters, php-cache integration tests) those keys can be rejected at runtime. This is the single most likely production surprise. Standardise on _ or . separators; add a unit test asserting key construction against your real pool before rollout.
Laravel PSR-6 gap No first-class bridge; you must write a custom cache store driver or adapter to reach the package from Cache::store(). Budget the adapter as part of the estimate; the decorator is not the hard part.
clear() / invalidation semantics Prefix-scoped clear() is not obviously safe — a decorator either cannot clear only its own keys or must delegate to a full-pool clear(), which in a shared Redis nukes other tenants. Verify against the pinned version; upstream php-cache has historically been conservative here. Assume full-pool clear() is unsafe; forbid cache:clear on shared stores; use per-key TTLs and version-stamped prefixes instead.
Abandonment / provenance Repo is marked [READ-ONLY], a split of the php-cache/cache monorepo; issues and PRs live elsewhere (issue tracker and Gitter, both low-activity). 2 stars, 0 dependents. Treat as vendorable source, not a supported dependency.
Metadata inconsistency Source says "last release 2022" while the package metadata says 2026-08-20. One of these is wrong; neither is a signal of active development. Confirm on Packagist before any ADR references a release date.
Key budget Long compound prefixes (env_tenant_feature_version_) eat into the 64-character minimum key budget the spec guarantees. Enforce a max prefix length in config; keep tenant IDs short or hashed.

Key questions.

  1. Do we actually hold PSR-6 pools in-process, or is this solving a problem our PSR-16/Cache facade already solves?
  2. What is the prefix composition rule (env, tenant, module, schema version), who owns it, and what is the max length?
  3. Are we prepared to own clear() semantics on a shared backend?
  4. Build vs. buy: the implementation is under ~100 lines of MIT-licensed decorator. Is a zero-dependent, read-only, 2-star package worth the supply-chain entry when vendoring is trivial and lets us fix the reserved-character problem?
  5. If we adopt, what is the exit trigger (CVE, PHP version break, PSR-6 spec change) and who executes the five-minute swap to the in-house class?

Recommendation: adopt the pattern, not the package. Vendor an equivalent decorator into app/Support/Cache under our own tests. If a dependency is mandated, pin it exactly and wrap it so the swap is one binding change.

Integration Approach

Stack fit. Assume Laravel 10/11, PHP 8.2+, Redis via predis/phpredis. Fit is good only in the "shared backend, multiple consumers" scenario. Fit is poor for the default case: Cache::remember() already namespaces by store prefix, and every additional layer between the facade and Redis is a debugging cost during incidents. The package's honest scope is PSR-6 consumers, which in a typical Laravel estate means a handful of libraries, not the whole application.

Migration path.

  1. Inventory first (1–2 days). Grep for CacheItemPoolInterface and php-cache/ across composer manifests. If the count is zero, stop — the package has no consumer and the exercise is over.
  2. Define the key grammar. {env}_{tenant|module}_{key} with separators restricted to _ or .; document max lengths per backend; add a validator that rejects reserved characters at the boundary.
  3. Prototype against the real pool. Wire PrefixedCachePool around one non-critical pool in a test environment. Assert: hit/miss parity, TTL preservation on save/saveDeferred, batch getItems/deleteItems correctness, and behaviour of clear().
  4. Build the Laravel bridge if and only if the facade must reach it. A custom store extending Illuminate\Cache\Repository that delegates to the PSR-6 pool, registered via Cache::extend() in a service provider and declared in config/cache.php. Keep it thin; it exists to translate PSR-16 calls into getItem/save, nothing more.
  5. Introduce incrementally. Start with a cache where a collision is inconvenient but not corrupting (derived view data, rate-limit counters). Never start with sessions or queue payloads.
  6. Cut over and de-risk. Once stable, evaluate replacing the package with the in-house decorator — same interface, no behaviour change, one binding edit.

Compatibility. Backward compatible by construction: prefixing is opt-in per pool, and unprefixed keys are untouched — which is also the migration hazard. Old and new keys will not collide, so a rollout creates a cold cache for migrated paths, not a correctness bug. Plan for a warm-up or accept a latency spike on the first deploy. Forward compatibility is bounded by the package's maintenance status; PSR-6 is stable and frozen in practice, so the realistic break vectors are PHP version deprecations and backend adapter changes, not the interface itself.

Sequencing. Grammar and validation → prototype → Laravel bridge (conditional) → single non-critical store → expand → replace with vendored copy. Explicitly do not sequence this ahead of work that is already planned to consolidate cache infrastructure; if a shared-cluster migration is on the roadmap anyway, fold prefixing into that design rather than shipping it as a standalone change.

Operational Impact

Maintenance. Low effort, low attention. The code is small and the interface is frozen, so the realistic maintenance burden is a Composer constraint bump every PHP major. The cost is not maintenance but ownership ambiguity: a read-only mirror repo with issues filed elsewhere and a Gitter channel as the support path means there is no one to escalate to. In practice the team owns it from day one, whether or not that is written down. Document it as internal code in the dependency register.

Support. No vendor, no SLA, no security-response process. For an MIT-licensed ~100-line decorator this is acceptable; for anything touching tenant isolation it is not, unless the team can read and patch the source themselves. Confirm the on-call engineer can debug it — the failure signature (mystery keys appearing in Redis, unexpected InvalidArgumentException on key validation) is not obviously traceable to a decorator without having read it.

Scaling. Negligible CPU cost — string concatenation per operation. Real scaling concerns are structural:

  • Key-space growth: compound prefixes plus per-tenant data multiply key count; watch Redis memory and eviction behaviour after enabling per-tenant prefixes, since eviction now removes one tenant's entries unevenly.
  • Blast radius of clear(): on a shared cluster, a full-pool clear from a prefixed pool is an estate-wide cache stampede. Restrict the relevant Artisan commands and alert on mass-eviction events.
  • Prefix churn: version-stamped prefixes (v2_) double memory during overlap. Budget for it or accept a stampede.

Failure modes. (a) Reserved-character keys throw at runtime — caught in prototype testing if you test against the real adapter, missed if you test against ArrayAdapter. (b) clear() behaves differently than assumed, either throwing or wiping the shared pool. (c) Silent cold cache after deploy — appears as latency, not errors, so instrument hit ratio before and after. (d) Debuggability regression: a logged key is now the prefixed form, so support runbooks and dashboards that filter on key names need updating. (e) Supply-chain: an abandoned package is a low-probability but unbounded-blast-radius dependency if PHP 9 or a PSR-6-adjacent spec change lands; the vendored alternative has the same risk but you can fix it in an afternoon.

Ramp-up. Under a day for an engineer comfortable with PSR-6. The learning is not the decorator — it is the prefix grammar, the invalidation model, and the PSR-6-vs-PSR-16 boundary in Laravel, which is where most teams get it wrong. Produce a one-page internal note covering the key grammar, the prohibited characters, clear() policy for shared stores, and the swap-to-vendored procedure; that note is the deliverable that makes the adoption reversible.

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.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc