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

Laravel Cacheable Laravel Package

ahmedzidan/laravel-cacheable

Laravel Cacheable adds automatic caching to your Eloquent models, so frequent queries are served from cache and invalidated on create, update, or delete. Drop in the trait, configure a TTL, and cut database load with almost no code changes.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

rinvex/laravel-cacheable (published under ahmedzidan/laravel-cacheable) is a trait-based query-result cache for Eloquent. It works by swapping the model's query builder so every get(), first(), count(), paginate(), and aggregate call is hashed into a cache key derived from the generated SQL plus bindings, then stored against a per-table tag. Writes and deletes flush the relevant tag. Architecturally this is a cross-cutting concern pushed down into the persistence layer — it fits cleanly into a conventional Laravel monolith or modular monolith where models are the single access path to data, and where a tag-capable cache store (Redis, Memcached) is already provisioned.

It does not fit event-driven, CQRS, or read-model architectures, and it fits poorly with any codebase that routinely reaches for the raw query builder, DB::table(), or hand-written SQL — those paths bypass the cache entirely, so you get inconsistent read semantics between Eloquent and non-Eloquent code.

Integration feasibility

Integration is mechanically trivial: composer require, add the trait to target models, ensure a tag-capable cache store, set a TTL. There is no service provider wiring to reason about, no config surface beyond the cache store, and no schema changes. The cost is not in installing it — it is in validating correctness. The package makes caching implicit: a developer reading User::where(...)->get() has no local signal that they are reading a cached snapshot. That implicit behaviour is the real integration risk, and it is a review-and-conventions problem, not a technical one.

Technical risk

The dominant risk is lifecycle: the repository is archived and explicitly marked abandoned, with 107 stars and zero dependents on the record. That is effectively no production user base and no maintenance. Concretely:

  • Framework drift. The package overrides newEloquentBuilder / newBaseQueryBuilder and subclasses Eloquent's Builder and Query\Builder. Laravel has changed return types, added strict signatures, and altered builder internals repeatedly across 8.x–11.x. Compatibility beyond the Laravel version it was last released against is unverified and will not be fixed upstream.
  • PHP drift. PHP 8.x deprecations and type-strictness changes are a realistic breakage surface for a package last touched in the Laravel 6/7 era.
  • Silent correctness failures. Cache keys are built from SQL strings and bindings. Queries using raw expressions, whereRaw with non-deterministic fragments, NOW()-style functions, connection-specific table prefixes, or tenant-scoped global scopes can collide or serve cross-tenant data if scoping is not part of the key. Stale reads after writes that occur outside the model layer (queue workers using raw SQL, other services writing the same tables, DB triggers) are guaranteed and undetectable.
  • Tag store coupling. Invalidation depends on cache tags. File and database cache drivers do not support tags, so the package's core invalidation story silently degrades or fails on those drivers.
  • Security posture. An unmaintained package that composes cache keys from query text is a supply-chain and multi-tenancy liability. With zero dependents and no maintainer, there will be no CVE response.

Net: low integration risk, high lifecycle risk, medium-to-high correctness risk.

Key questions

  1. What is the actual read-to-write ratio and query latency budget? If p95 model reads are already under ~10ms, the payoff does not justify the risk.
  2. Is the target cache store Redis/Memcached cluster-wide, and is tag support guaranteed in every environment including local and CI?
  3. Does any code path write to these tables outside Eloquent (other services, jobs, bulk loaders, DBA scripts)? If yes, invalidation is structurally unsound.
  4. Is the application multi-tenant? If so, is tenant identity provably part of every cache key?
  5. Are we willing to vendor/fork the ~small source surface (~10 files) into app/ or an internal package and own it, versus depending on an archived repository?
  6. Which Laravel and PHP versions are on the roadmap for the next 18 months, and who owns revalidating this code against each upgrade?

Integration Approach

Stack fit

Best fit: Laravel 8–10 on PHP 8.0–8.2, Redis already in the stack, models as the sole data access path, read-heavy workloads with expensive query shapes (multi-join listings, aggregate dashboards, filter-heavy index pages). Poor fit: Laravel 11+, multi-tenant SaaS, services with mixed ORM/raw-SQL access, teams without an existing cache-invalidation discipline, or anything with a compliance requirement for demonstrable dependency provenance.

Migration path

Do not add the archived repository as a Composer dependency from Packagist. Three viable paths, in order of preference:

  1. Reimplement the pattern internally (~2–4 engineer-days). The mechanism is small: a trait that overrides the model's builder, wraps get/first/paginate/count in Cache::tags([$table])->remember($key, $ttl, $callback), and flushes the tag in saved/deleted model events. Owning ~200 lines of code is strictly cheaper than owning an unmaintained dependency, and it lets you bake in tenant scoping and observability from day one.
  2. Fork and vendor. Copy the source into app/Support/Cacheable or an internal Composer package with a pinned namespace, add tests, and treat it as first-party code. Acceptable if the team wants the exact existing semantics.
  3. Adopt a maintained alternative. genealabs/laravel-model-caching occupies the same design space with active maintenance; spatie/laravel-responsecache solves the HTTP-layer variant if the real goal is response latency rather than model-level reuse. Evaluate either against the same correctness checklist.

For an existing deployment already using the package: freeze the version, pin it in composer.json with an exact constraint, vendor it, and schedule replacement within one quarter. Do not carry it through the next major Laravel upgrade.

Compatibility

Verify before any pilot: exact Laravel constraint in composer.json against the target app version; PHP 8.2/8.3 deprecation surface; that newEloquentBuilder and newBaseQueryBuilder overrides do not conflict with any other package already extending the builder (common collision with soft-delete extensions, audit-log packages, and search integrations); that the cache store supports tags in all environments; and that global scopes (tenancy, soft deletes) are reflected in the cache key.

Sequencing

  1. Spike (1–2 days). Instrument one high-traffic read model. Measure hit rate, p50/p95 latency delta, and Redis memory growth. Confirm tags work end to end.
  2. Correctness harness (2–3 days). Tests that assert invalidation on create/update/delete/restore/forceDelete, cross-tenant isolation, and behaviour under raw-SQL writes. This is the gate — no green tests, no rollout.
  3. Single bounded context. Apply to one low-risk, read-heavy model set. Add cache-hit/miss metrics and a kill switch (config flag that bypasses the cache).
  4. Expand by measured benefit only. Each additional model set must show a latency or DB-load win.
  5. Decision gate at 30 days. Either the pattern is owned internally and documented, or it is removed entirely.

Operational Impact

Maintenance

The upstream maintenance cost is zero and will stay zero — the repository is archived. All maintenance is transferred to your team the moment it ships. Practically that means: revalidating the builder overrides against every Laravel minor, owning any security response, and owning documentation so that "why is this read stale" is answerable by an on-call engineer at 3am. Budget roughly 1–2 engineer-days per Laravel major upgrade for revalidation, plus ongoing review overhead enforcing the convention that models must not be bypassed.

Support

No vendor, no maintainer, no issue tracker, no security contact. Internal support depends entirely on whether the pattern is understood by more than one person. Mitigate by keeping the surface small (prefer internal reimplementation over vendoring the full package), documenting the invalidation contract in the repo, and adding a runbook entry: "stale data suspected → flush tag {table} → confirm."

Scaling

Read scaling is the point: offloading repeated queries to Redis reduces primary DB load roughly in proportion to hit rate, and tag-based invalidation scales acceptably because flushes are per-table rather than global. Watch three things: (1) cache stampede on TTL expiry for hot keys — the package does not implement locking, so a cold tag under high concurrency can produce a thundering herd against the DB; mitigate with jittered TTLs or a lock wrapper. (2) Redis memory growth from large result sets — cache keys hash the full SQL, so highly variable filter combinations produce a combinatorial key space; enforce bounded filter surfaces and TTLs. (3) Tag flush cost — flushing a busy table's tag invalidates everything for that table, so write-heavy tables will see low effective hit rates and add churn without benefit.

Failure modes

  • Stale reads after out-of-band writes. Highest-probability, highest-impact. Silent; surfaces as user-reported inconsistency.
  • Cross-tenant leakage. If tenant scoping is not in the cache key, one tenant can read another's data. This is the failure mode that should stop the project outright if it cannot be proven absent.
  • Cache store unavailable. Depending on config, either hard failure (reads error out) or graceful degradation to DB. Test both; prefer explicit fail-open with alerting over silent latency collapse.
  • Builder incompatibility after a framework upgrade. Manifests as fatal errors or, worse, subtly wrong query results in staging only.
  • Thundering herd on invalidation. A single write to a hot table flushes the tag and forces full re-query under load.
  • Driver without tag support. Invalidation becomes a no-op; stale data persists until TTL. Will pass local dev on array and fail in production only if the driver differs.

Ramp-up

Low to get running (hours), moderate to operate safely (weeks). Engineers need to internalise three things: which models are cached, what the invalidation contract is, and that any write not going through Eloquent breaks the guarantee. A single 60-minute walkthrough plus a repo-level ADR covering the failure modes above is sufficient onboarding for a mid-level team.

Recommendation: do not adopt the archived package as a dependency. Either reimplement the ~200-line pattern internally with tenant scoping and metrics baked in, or evaluate genealabs/laravel-model-caching against the same correctness harness. Treat implicit model-level caching as an optimisation to be earned by measurement, not a default.

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