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

In Memory Cache Laravel Package

beste/in-memory-cache

A PSR-6 in-memory cache for PHP that works as a sensible default implementation and in tests. It supports PSR-20 clocks, including frozen clocks, so you can test time-based expiry without a real cache server. Simple, fast, and dependency-free. Install with composer require beste/in-memory-cache.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — adjacent, not plug-in. The package implements PSR-6 (Psr\Cache\CacheItemPoolInterface) only. Laravel's cache layer is not PSR-6; it is built on Illuminate\Contracts\Cache\Store with a PSR-16-shaped surface (get/put/forget). There is no first-party Laravel bridge that lets Cache::store('in_memory') resolve a PSR-6 pool. Any claim that this "aligns seamlessly with the Cache facade" should be rejected in review — the integration is a deliberate adapter, not a config line.

Where it genuinely fits:

  • Test seams where the SUT already type-hints CacheItemPoolInterface (Symfony-derived libraries, Geocoder, PSR-6 consumers pulled in transitively). Here it is a drop-in with zero glue code.
  • Deterministic TTL testing via the injectable PSR-20 clock. This is the standout capability and the hardest thing to replicate cheaply with Mockery or Carbon::setTestNow() against a real store.
  • Behavioral reference: a small, readable, spec-compliant pool that teams can copy or fork when they need a PSR-16 Store fake rather than a PSR-6 pool.

Integration feasibility — low effort, but the effort is in the adapter, not the package. composer require is one line and there are no transitive dependencies. The API surface is four methods. Two credible paths:

  1. Test-only, direct construction (hours). Instantiate InMemoryCache in tests, inject it where a PSR-6 pool is accepted. No Laravel wiring, no config changes.
  2. Production driver behind Cache::store() (days). Requires writing and owning a Store implementation that maps get/put/forget/flush onto the PSR-6 pool, handling CacheItem misses, TTL translation from seconds to DateInterval, and Laravel's flush/forever semantics. That is roughly 100–150 LOC plus its own test suite — and it becomes code you maintain forever.

Path 2 deserves scrutiny: Laravel already ships the array store, which is in-memory, per-request, TTL-aware, and supported by the framework. For Laravel-native code, array covers most of the same ground. The honest differentiators are only (a) PSR-6 interface compliance for third-party libraries and (b) the injected clock. A TPM should anchor the business case on those two and explicitly retire the "cheap Redis fallback" narrative.

Technical risk:

  • PHP ≥ 8.3 floor as of 1.5.0. Laravel 10 apps on PHP 8.1/8.2 must pin 1.4.x. Verify with composer why-not beste/in-memory-cache 1.5.
  • The "fallback" story does not survive PHP-FPM. Under FPM the pool is created and destroyed per request; it cannot absorb a Redis outage because nothing survives to the next request. Only in long-lived processes (Octane, Swoole, queue workers) does it persist — and there it becomes a liability (see Operational Impact).
  • Unbounded growth. No LRU, no max-size, no memory cap. In a worker or Octane process, a hot cache key space becomes a leak unless every write has a TTL and a bounded key universe.
  • Not thread-safe / not cross-process consistent. Two workers see two different caches; correctness assumptions about cache hit rates or read-your-writes will silently break.
  • Vendor concentration. 26 stars, 0 dependents, effectively a single maintainer. Mitigated by the code being small and MIT-licensed — forkability is the real insurance policy, not the release cadence.
  • Release date anomaly. The metadata shows a 2026-08-20 release; confirm this is genuine and not a feed artifact before citing "actively maintained" in any decision record.

Key questions for the team:

  1. Do we actually have production code paths that depend on a PSR-6 pool, or only PSR-16/Laravel-cache call sites? (If the latter, this is a test utility, full stop.)
  2. What problem are we solving — flaky tests, or runtime resilience? They lead to different adoption decisions and different owners.
  3. Are we on PHP ≥ 8.3 everywhere, or does a mixed fleet force a version split?
  4. If we need Cache::store() integration, who owns the adapter and its tests, and what is the sunset criterion?
  5. Does Laravel's array store already satisfy the test requirement? If yes, the marginal value collapses to the frozen-clock TTL testing only.
  6. What is our fork-and-own threshold for single-maintainer dependencies under 1k LOC?

Integration Approach

Stack fit.

Context Fit Notes
Laravel 11/12, PHP 8.3/8.4/8.5 Test-only: strong. Runtime: adapter required No native PSR-6 consumption in the framework
Laravel 10, PHP 8.1/8.2 Pin 1.4.x 1.5.0 drops < 8.3
Symfony / PSR-6-native code Strong Direct construction, no glue
Plain PHP libraries with PSR-6 seams Strong Zero dependencies
Any FPM-served production request path Weak Per-request lifetime nullifies the fallback value

Migration path. Three sources of existing pain, in order of likely payoff:

  1. Mockery::mock(CacheItemPoolInterface::class) proliferation → replace with a real InMemoryCache. Removes expectation-drift bugs and lets tests assert on actual cache state (isHit(), get()) rather than on method-call choreography.
  2. Hand-rolled array-based PSR-6 fakes → delete and depend on the package. This is the cleanest "build vs. buy" win; the replacement is a one-line constructor change.
  3. symfony/cache ArrayAdapter used purely as a test double → optional swap. Low urgency; ArrayAdapter also implements PSR-6 and is already in-tree. Do not migrate without a specific reason.

Explicitly do not migrate production cache reads/writes onto this pool. If a fallback story is genuinely required, the correct design is Laravel's failover cache driver (Laravel 11+) pointing at a durable secondary, not an in-process pool.

Compatibility. Pin with a caret constraint and test both the floor and ceiling of your PHP matrix in CI. Check composer why-not before any framework upgrade; the PHP floor moving to 8.3 will be the recurring breakage vector. Watch for the PSR-20 clock being injected only in tests — never resolve a frozen clock in a production container binding.

Sequencing.

  1. Week 0 — validate the premise. Grep the codebase for CacheItemPoolInterface and PSR-6 usage. If the count is zero outside tests, scope the decision to "test dependency" and stop.
  2. Week 1 — pilot in one test suite. Convert a single flaky or TTL-dependent suite. Add a frozen-clock test for at least one expiration path. Measure: suite runtime, flake rate over 20 runs.
  3. Week 2 — standardize. Add a small test helper (e.g., a CacheFactory trait) so no test constructs the pool ad hoc. Document the boundary: "test doubles only; not a runtime driver."
  4. Week 3 — decide on the adapter. Only if step 1 surfaced a real production PSR-6 requirement. Otherwise, close it out and record the decision.
  5. Ongoing — vendor-risk register. Log the dependency with its single-maintainer status, the PHP floor, and the fork trigger.

If the adapter is pursued, the shape is a thin Illuminate\Contracts\Cache\Store implementation delegating to the pool: get($key) → pool->getItem($key) returning the value or null; put($key, $value, $seconds) → getItem()->set()->expiresAfter($seconds) then save(); forever() → set() with no expiry; flush() → pool->clear(). Budget for the ugly parts: Laravel's many()/putMany() batching, TTL-null semantics, and Cache::increment/decrement, which have no PSR-6 equivalent and must be emulated read-modify-write.

Operational Impact

Maintenance. Near-zero surface area, semver discipline, published changelogs, and a small codebase — the code itself will not surprise you. The maintenance burden is entirely policy: version floors that track PHP releases (1.3 → 8.4, 1.4 → 8.5, 1.5 → drop < 8.3) mean an upgrade cadence obligation roughly once per PHP release cycle. Assign an owner and put the pin in the dependency-upgrade runbook.

Support. No vendor SLA. Single maintainer, low star count, zero dependents means community answers will be scarce — your team is the support tier. Mitigate with the fork escape hatch: at under ~1k LOC and MIT licensing, a hard fork is an afternoon, not a quarter. Record this explicitly in the risk register so it is a decision, not a surprise.

Scaling. Treat this as process-local state with a request-sized lifetime. On FPM it is naturally bounded — it dies with the request. On Octane, Swoole, or long-lived queue workers it persists and therefore must be bounded by policy: every write carries an explicit TTL, the key space is finite and enumerated, and the pool is cleared at worker lifecycle boundaries (e.g., Octane::tick or a job-middleware reset). Horizontal scaling is a non-goal — each process gets its own island, and any code that assumes a warm shared cache will behave differently in production than in a single-process test.

Failure modes to design against:

  • Silent inconsistency across workers — cache hit rates drop to per-worker behavior; anything treating the cache as shared state (rate limiting, deduplication, feature flags) breaks quietly rather than loudly. This is the highest-severity risk because it fails without an error.
  • Unbounded memory growth in long-lived processes, presenting as OOM kills under load and typically misattributed to the application, not the cache.
  • Clock leakage into production — a frozen or test clock bound into a non-test container silently freezes TTL evaluation, so items never expire. Guard the binding to the testing environment.
  • Divergent semantics under the adapter — if the Store bridge is built, increment/decrement/many emulation gaps produce count drift that only appears under concurrency.
  • Upgrade breakage from the PHP version floor landing mid-quarter, blocking a framework patch.

Ramp-up. One to two hours for a developer already comfortable with PSR-6 — the README is sufficient and the package is small enough to read end to end. The non-obvious learning is conceptual, not syntactic: understanding that PSR-6 pools and Laravel's cache are different abstractions, and that in-memory means per-process. Both belong in the team's testing guide as a short section, not a wiki page. Budget a half-day of tech-lead time for the decision record and the boundary documentation, and treat that as the actual cost of adoption.

Recommendation. Adopt as a require-dev dependency for PSR-6 test seams and deterministic TTL testing; do not adopt as a production cache driver. Revisit only if the PSR-6 usage audit surfaces real production demand, at which point the adapter is a scoped, owned work item rather than an assumption.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator