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

Namespaced Cache Laravel Package

cache/namespaced-cache

A PSR-6 decorator that scopes a shared cache pool to a single namespace, so clear() invalidates only that namespace. Includes tag support, generation-key safety, and | hierarchical key deletion.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the package actually is

  • A single-purpose PSR-6 decorator: NamespacedCachePool wraps any Psr\Cache\CacheItemPoolInterface and transparently prefixes every key with a namespace string (e.g. acme:user:42). Callers see namespace-relative keys; the backend sees prefixed ones.
  • Since 1.0.0 it also implements HierarchicalPoolInterface from the php-cache family, so it composes with sibling decorators (e.g. cache/hierarchical-cache).
  • Scope is intentionally tiny: one class, no service provider, no facade, no config file, no framework integration, MIT licensed, READ-ONLY split of the php-cache/cache monorepo.

Architecture fit

  • Critical correction to prior framing: this is not a Laravel package. Laravel's cache layer (Illuminate\Contracts\Cache\Repository / CacheStore) is not PSR-6; it is a Laravel-specific contract with remember, tags, increment, and a prefix config option. There is no Cache::namespace(...) method, no auto-discovery, no container binding shipped by this package. Any such ergonomics would be code we write on top.
  • Realistic leverage points in a Laravel-centric estate:
    1. Mixed-framework estate — a shared Redis pool consumed by Laravel apps and PSR-6 consumers (Symfony components, php-http cache plugin, third-party SDKs that demand a PSR-6 pool). Here the decorator is genuinely useful glue.
    2. PSR-6 libraries inside Laravel — whenever a dependency requires a CacheItemPoolInterface, we need a pool adapter anyway; namespacing that pool costs one extra line.
    3. Deploy/version isolation — bumping the namespace (v1 → v2) is a cheap, atomic logical invalidation primitive for blue-green or canary rollouts, without touching keys at call sites.
  • Where it is a poor fit: a pure-Laravel app needs none of this. Laravel's per-store prefix, Cache::tags() (Redis/Memcached/array drivers), or a 20-line tenantKey() helper deliver equivalent isolation with zero third-party dependency and zero dependency-resolution risk. Build-vs-buy must be justified by cross-runtime reuse, not by Laravel use alone.

Integration feasibility

  • Integration cost is low (single class, Composer-only), but the gating factor is dependency resolution, not code. Modern Symfony 6/7 and many current libraries require psr/cache ^2.0/^3.0; a 1.x-era decorator pinned to psr/cache ^1.0 will conflict. This must be verified before any design work.
  • Registering it in Laravel means manual container bindings (one named binding per namespace, or a small factory) plus a PSR-6 adapter over the chosen Laravel store if we want it to share the app cache. That adapter is the real work item — and it is our code, not the package's.
  • No Laravel version coupling in the package itself, which is a mild plus (it cannot break on a framework upgrade); the coupling risk sits entirely in the PSR ecosystem.

Technical risk

  • Adoption / bus factor: 14 stars, 0 dependents, no downstream validation. The repository is a read-only split, so issues and PRs are redirected to the monorepo — upstream throughput is outside our control, and a needed patch likely means a fork. Treat this as vendored internal utility, not a living dependency.
  • Semantics we must verify, not assume: whether clear() is namespace-scoped or delegates to a full-pool flush (a global flush in a multi-tenant cache is a data-loss incident), and whether namespace-wide operations rely on getItems() over the underlying pool — which on Redis can mean KEYS/SCAN and blocking I/O at scale.
  • Decorator ordering with tags: namespaced + tag-aware composition is untested by us; wrong ordering silently breaks invalidation.
  • Observability regression: backend keys no longer match application keys, so cache debugging, hit-rate dashboards, and any tooling keyed on key names degrade unless we record the namespace mapping.
  • Silent misconfiguration: a typo'd namespace does not error — it silently produces a cold cache and a thundering-herd event on the database.

Key questions for engineering

  1. Do we have any PSR-6 consumer today, or is this speculative? If speculative, the answer is "build the helper instead."
  2. Does the package's psr/cache constraint resolve against our current lockfile? (Blocker check — do this first.)
  3. What is clear()'s exact scope, and what does a namespace-wide purge cost against our Redis topology?
  4. Do we require tag-based invalidation in addition to namespacing? If yes, the decorator alone is insufficient.
  5. What is the namespace taxonomy (tenant:{id}, env:{name}, svc:{name}:v{n}), and who owns it as a contract?
  6. Who owns the fork if upstream stalls or a patch is needed?
  7. What is the acceptable cache-miss budget when a namespace is introduced or bumped (cold-start blast radius)?

Integration Approach

Stack fit matrix

Context Fit Rationale
Laravel-only app, Redis/Memcached Poor Native prefix config, Cache::tags(), or a key helper cover it with no dependency.
Laravel app consuming PSR-6 libraries Good Needs a pool adapter regardless; namespacing is additive.
Shared cache across Laravel + non-Laravel services Strong The clearest justification: one convention across runtimes.
Symfony 6/7 services Redundant Symfony's cache config already exposes a namespace option per adapter.
Multi-tenant SaaS on a single Redis Conditional Only if clear() is proven namespace-scoped and key-prefix collision is enforced.

Migration path

  1. Phase 0 — Feasibility (1–2 days). Prove Composer resolution (psr/cache, cache/* adapters) against the current lockfile on a throwaway branch. If it conflicts, stop and either fork or select an alternative. This phase kills or greenlights the initiative.
  2. Phase 1 — Adapter + POC (3–5 days). Choose one PSR-6 pool adapter over our existing store (Redis is the pragmatic choice). Wrap it with NamespacedCachePool for a single low-risk consumer (feature flags or read-through reference data). Confirm clear() semantics with a destructive test in a sandboxed Redis DB.
  3. Phase 2 — Convention + bindings. Publish the namespace taxonomy as a written contract. Bind pools in the service container as named singletons (per tenant or per service), never construct the decorator ad hoc at call sites.
  4. Phase 3 — Gradual rollout. Move read-heavy paths first, write-heavy/session-critical paths last. Gate with a feature flag; keep a bypass path to the unprefixed pool for incident response.
  5. Phase 4 — Decommission ad hoc prefixes. Only after the new convention is enforced in CI (a lint rule or static check rejecting hand-rolled "$tenant:" string concatenation).

Compatibility concerns

  • Pin the exact package version (~1.2) and record the resolved psr/cache version in the architecture decision record.
  • Maintain a documented fork-and-patch procedure; assume we will use it at least once.
  • Confirm PHP version constraints and that the chosen pool adapter supports the same psr/cache major.
  • Do not couple the namespace taxonomy to the application release train — namespace selection should be configuration, so a bump is a config deploy, not a code deploy.

Sequencing guidance

  • Adapter before decorator; decorator before conventions; conventions before observability; observability before broad rollout. Introducing namespaces without per-namespace hit/miss metrics leaves the team blind during the first incident.
  • Plan for a deliberate cold-cache event on every namespace introduction or bump: schedule it, warm the top-N keys, and have database headroom ready.

Operational Impact

Maintenance

  • Low code-maintenance burden, non-trivial ownership burden. Budget a named owner for the fork, the taxonomy document, and the Composer constraint. Review upstream tags at each dependency-refresh cycle; expect to skip most of them.
  • No meaningful security surface: the package performs no I/O, no deserialization, and no network calls of its own — it only manipulates key strings. Supply-chain risk reduces to the standard Composer vetting for a small MIT package.
  • Exit strategy is cheap and should be documented up front: replacing the decorator with an in-house prefixing pool is a bounded, few-hour change because the interface is PSR-6, not a vendor contract. This is the strongest argument for accepting the low-adoption risk.

Support

  • Requires a runbook covering: how to translate an application key to a backend key, how to enumerate keys in a namespace safely, how to purge a single namespace, and what cache:clear now means for each pool.
  • On-call friction is real: "the cache is stale for one tenant" becomes a namespacing question rather than a generic cache question. Train the first-line responders on the taxonomy.
  • Add per-namespace metrics (hit rate, item count, memory estimate) — without them, triage reverts to manual Redis inspection.

Scaling

  • CPU overhead is negligible (string concatenation per operation). The scaling risks are storage and operation shape, not throughput:
    • Key length growth multiplies across millions of keys; on a memory-constrained Redis this is a measurable capacity line item.
    • Cluster slot distribution shifts whenever the prefix changes, which is fine for steady state but means a namespace bump effectively reshards and cold-starts.
    • Namespace-wide operations are the dangerous primitive: enforce TTLs everywhere so purge-by-iteration is never the primary invalidation mechanism.
  • Horizontal scaling of the backend is unaffected; namespacing is a logical, not physical, partition. Do not mistake it for isolation — noisy-neighbour eviction still crosses namespaces on a shared maxmemory-policy.

Failure modes

Scenario Impact Mitigation
clear() flushes the whole pool rather than one namespace Cross-tenant cache wipe; potential DB overload Verify destructively in sandbox before adoption; forbid namespace purge in shared production pools if unscoped
Namespace typo or missing config Silent 100% miss rate; thundering herd to origin Fail-fast on unset namespace; alert on sudden per-namespace hit-rate drop
Namespace bump during deploy Deliberate cold cache, latency spike Schedule, pre-warm top-N keys, gate by canary
Prefix collision between services Cross-service data leakage Enforce taxonomy uniqueness in CI; reserve a per-service root segment
Namespace-wide purge via getItems()/SCAN on a large Redis Blocked event loop, latency SLO breach TTL-first invalidation; cap namespace size; purge out-of-band
Upstream stalls or dependency conflict appears Upgrade blocked; forced fork Documented fork path; pinned version; cheap exit strategy
Decorator composed in wrong order with tags Silent invalidation failure Integration test asserting tag invalidation through the decorator

Ramp-up

  • Engineering: ~2 days to POC, ~1 week to first production namespace; most of that is the pool adapter, not the package. Documentation needs are: taxonomy contract, container binding examples, and an explicit "do not hand-prefix keys" rule.
  • Support/on-call: half-day enablement on the runbook and metrics; low ongoing cost if observability is in place from day one.

TPM recommendation Approve for a bounded POC only if a PSR-6 consumer or cross-runtime shared cache exists today, and only after the psr/cache constraint resolves cleanly. If the estate is Laravel-only, decline and fund a ~20-line key-prefix helper plus a CI lint rule instead — it delivers the isolation benefit with no dependency-resolution risk, no fork obligation, and no observability regression. Should the POC proceed, treat the package as a vendored internal utility with a documented exit, not as a strategic dependency.

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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel