spiritix/lada-cache
Lada Cache is a Redis-based, fully automated query cache layer for Laravel. It transparently caches Eloquent and Query Builder queries, invalidates only the affected rows or tables, requires no code changes, and scales horizontally with Debugbar support.
Architecture fit. Lada Cache is a transparent query-cache layer that inserts itself between Eloquent/Query Builder and the database via a Lada-aware connection subclass registered with DB::extend(). For a Laravel monolith with an Eloquent-heavy read path and repetitive query patterns, the architectural fit is strong: it requires no application code changes beyond a trait on a shared BaseModel, and invalidation is automatic on insert/update/delete/truncate. This is meaningfully different from manual Cache::remember() usage, where the dominant failure mode is stale data from forgotten invalidation. For a TPM, that means the primary integration cost is configuration and verification, not refactoring — an attractive ratio, provided the team accepts an implicit caching layer in the data access path.
Integration feasibility. Composer install plus package discovery, a published config file, and the trait on a base model. Constraints are explicit: Redis is mandatory (no alternative backend), Laravel 12/13 and PHP 8.3 for 6.x, and the version matrix is narrow at both ends. Redis is already present in most Laravel stacks as the cache/session driver, so infrastructure work is likely limited to confirming a dedicated logical database or connection (lada-cache.redis_connection, default "cache") and memory headroom. The withoutCache() escape hatch is important for feasibility: it gives an incremental, per-query rollback path that does not require disabling the package globally. The lada-cache:disable/:enable commands plus LADA_CACHE_ACTIVE provide an env-level kill switch, which is the single most reassuring property for a production rollout.
Technical risk. The main risks are correctness and observability, not installation. Known limitations are real and must be mapped against the application: raw SQL (DB::select(), DB::statement()) is not cached by design; third-party packages with custom query builders may bypass caching; UNION/INTERSECT/advanced expressions and composite or unconventional primary keys degrade to table-level invalidation, which is correct but coarser and can cause eviction storms on hot tables. Multiple named connections only work through Lada's connection integration. Because the layer is transparent, stale-read incidents would surface as data bugs rather than cache bugs — a diagnosis cost that must be planned for. Maturity signals are mixed: 592 stars, MIT license, an active changelog through 6.1.1 with a 2026-05-22 release, and a documented pattern of point releases fixing invalidation and row-tagging defects (6.0.2, 6.0.3, 6.1.1). Zero dependents on the listed metric and the pre-1.0-scale opportunity score argue for treating this as a single-maintainer dependency.
Key questions.
DB::select(), or third-party-builder traffic that would silently bypass the cache — and does the residual cached surface still justify the change?Stack fit. Best fit is a Laravel 12/13 service on PHP 8.3+, Eloquent-centric, Redis already in the stack, and read-heavy with redundant per-request queries. Poor fit is a raw-SQL-heavy reporting service, a polyglot database layer, or an application pinned below Laravel 12 without appetite for upgrade. Note the version matrix forces a decision: adopting 6.x requires Laravel 12/13 and PHP 8.3, while 5.x covers Laravel 9–11 on PHP 8.0+. Teams mid-upgrade should sequence Lada adoption after, not alongside, the framework upgrade.
Migration path. There is no data migration; the migration is behavioral. Recommended path: (1) install and publish config in a staging environment with LADA_CACHE_ACTIVE=false to verify the service provider registers cleanly and nothing in the query pipeline breaks; (2) enable with a narrow include_tables allowlist covering two or three high-read, low-write tables; (3) instrument hits/misses/invalidations via the Debugbar integration in staging only; (4) promote to production behind the env flag with the allowlist intact; (5) widen the table set after observing invalidation rates. Config-level include_tables/exclude_tables gives a staged blast radius that is far safer than a global enable.
Compatibility. The transparent connection subclass is the highest-friction integration point. Anything that wraps, decorates, or replaces the connection or query builder is a candidate for conflict: Telescope, Debugbar, query-logging middleware, read/write splitting, tenant-aware connection switchers, and packages with custom builders. Telescope and Debugbar are explicitly patched in the changelog (5.0.1, 6.1), which means these interactions are known and have historically broken on upgrade — treat each as a required regression test rather than an assumption. Laravel Octane and long-running workers deserve explicit verification because cached connection state persists across requests.
Sequencing. Framework upgrade → Redis capacity and connection isolation → package install with cache disabled → allowlist pilot on non-critical tables → observability and Debugbar validation in staging → production enablement behind env flag → progressive allowlist expansion. Cache flush and toggle commands should be documented in the runbook before step five, and the migration auto-flush event (6.0) should be confirmed against the deploy pipeline so schema changes do not serve stale results.
Maintenance. Ongoing work is narrow but nonzero: no cache code to write, but the package must track Laravel and PHP releases, and this dependency's history shows each framework bump arriving as a versioned release with a cluster of invalidation fixes immediately after. Budget for validating on every Laravel minor upgrade and for pinning the version deliberately. The single-maintainer risk is the standing concern; mitigation is a fork-ready posture (MIT license permits it) and a documented rollback to LADA_CACHE_ACTIVE=false, which requires no code revert.
Support. Support surface is external to the team — GitHub issues from one maintainer. Internal support burden concentrates in diagnosis: when data looks wrong, engineers must now check "is this stale cache?" before "is this a query bug?" That is a new troubleshooting branch that must be written into the runbook and into on-call expectations. The Debugbar collector and lada-cache:flush are the two tools that make this tractable; both should be documented with the exact commands.
Scaling. This is where the package earns its place. Redis-backed, cluster-ready, and horizontally scalable, it moves repeated read load off the RDBMS and lets application replicas scale without proportional database growth. The README's honest framing of 5–95% gains with ~10–30% typical improvement is credible and should be adopted directly into expectations rather than inflated. Two scaling caveats matter operationally: large result payloads still incur serialization and transfer cost, so caching a 500MB result set buys little; and table-level fallback invalidation on hot tables can produce eviction churn that increases Redis traffic without improving hit rates. Sizing must account for a new high-volume keyspace sharing Redis with sessions and queues — connection isolation is strongly advised.
Failure modes. Ranked by operational severity: (1) stale reads from missed or coarse invalidation — the highest-impact and hardest-to-attribute failure, mitigated by withoutCache(), the global disable flag, and lada-cache:flush; (2) silent bypass where raw SQL or third-party builders skip caching entirely, producing confusingly flat performance rather than an error; (3) Redis unavailability, which converts the cache into a hard dependency on the read path — confirm the degradation behavior is fail-open to the database before production; (4) upgrade regressions in the connection subclass breaking query execution outright, which is loud and therefore manageable; (5) eviction pressure pushing sessions or queued jobs out of Redis, which is an infrastructure failure with a caching root cause. Each of the first three needs an explicit, rehearsed response.
Ramp-up. Low for install, moderate for correct operation. A mid-level Laravel engineer can complete installation in under a day; understanding which queries are cached, which fall back to table-level tagging, and what invalidates them takes a sprint of observation with Debugbar in staging. The real ramp-up cost is organizational: teaching the team that a transparent cache is now in the data path, that withoutCache() exists for freshness-critical reads, and that "stale data" is a first-class hypothesis. Recommended pilot scope is a single bounded service or a small set of read-heavy tables with an owner, a documented rollback command, and a two-week observation window before wider enablement.
How can I help you explore Laravel packages today?