Model or dataset
mike-bronner/laravel-model-caching avatar
mike-bronner/laravel-model-caching

mike-bronner/laravel-model-caching: automatic Eloquent query caching with self-invalidation

Eloquent model-caching made easy.

2,376 stars231 forksPHPMIT

At a glance

What is it?
A trait-based caching layer for Eloquent that caches model queries and eager-loaded relations and flushes them when models change. It fits read-heavy Laravel apps on Redis, and it quietly skips more query shapes than the README's headline suggests.
Who is it for?
Adopt it if you run Laravel 12 or 13 on PHP 8.2 or newer, your reads outnumber writes, and you already operate Redis or Memcached. Skip it if your hot paths are lazy-loaded relations, select() projections, or code inside transactions, because those bypass the cache or need a manual flushCache() call.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: repeated Eloquent reads and the invalidation bookkeeping around them

Every Laravel developer has written Cache::remember with a hand-built key and then forgotten one of its variants in an observer. The README frames the package as the answer to exactly that: add a trait to your models, query normally, and let the package handle both the caching and the invalidation. The target user is an application with many repeated Eloquent queries on read-heavy pages, where the cost of a stale or missing cache entry is a slow page rather than a wrong answer. The package's own summary claims typical improvements between 100% and 900% fewer database queries on such pages. That number comes from the project, not from an independent run, and it will depend heavily on query shape and hit rate. The more useful part of the pitch is the bookkeeping argument: cache keys and forget calls stop being something a human maintains. If your application already has a disciplined caching layer with explicit keys, this package replaces that discipline with a convention, and conventions have edges.

How the Cachable trait intercepts queries and flushes them on writes

The mechanism is a trait, GeneaLabs\LaravelModelCaching\Traits\Cachable, applied to a model or to a shared base model. Once applied, the package takes over query execution for that model: the README lists get, first, find, all, paginate, pluck, value and exists as cached operations, plus the aggregations count, sum, avg, min and max, plus eager-loaded relationships brought in through with(). When a model is created, updated or deleted, the relevant entries are flushed automatically, and the README's blog example notes that creating a Comment invalidates cache for both Post and Comment queries. The trait approach means the cache layer sits inside Eloquent's builder rather than beside it, which is why no keys appear in application code. The same placement explains the gaps. Anything that does not go through the model's builder, such as raw DB::table() writes, does not trigger invalidation, and the README calls this out for the User model specifically. Configuration lives in config/laravel-model-caching.php with keys cache-prefix, enabled, use-database-keying, store and fallback-to-database, each mapped to an environment variable. The use-database-keying option defaults to true and folds the database connection and name into cache keys, which matters when one application talks to several databases or serves several tenants from one cache.

Installing laravel-model-caching and caching your first model

Installation is a single Composer command, and the README states the service provider is auto-discovered, so no manual registration step is needed.

bash
composer require mike-bronner/laravel-model-caching

After that, the recommended pattern is a base model that every other model extends. The trait import path matters here, since the package namespace is GeneaLabs even though the repository lives under mike-bronner.

php
<?php

namespace App\Models;

use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use Illuminate\Database\Eloquent\Model;

abstract class BaseModel extends Model
{
    use Cachable;
}

With that in place, an ordinary query on a model that extends BaseModel is cached without further changes. The README's blog example uses eager loading, which is the case that benefits most, because lazy-loaded relations are not cached.

php
$posts = Post::with('comments', 'tags')
    ->where('published', true)
    ->latest()
    ->paginate(15);

To change behaviour you publish the config file, which the README shows as php artisan modelCache:publish --config. That writes config/laravel-model-caching.php containing cache-prefix, enabled, use-database-keying, store and fallback-to-database. The environment variables are MODEL_CACHE_ENABLED (default true), MODEL_CACHE_STORE (default null, meaning the default store from config/cache.php), MODEL_CACHE_USE_DATABASE_KEYING (default true) and MODEL_CACHE_FALLBACK_TO_DB (default false). If you want the application to keep serving reads when Redis is unreachable, set MODEL_CACHE_FALLBACK_TO_DB=true, which the README describes as falling back to direct database queries instead of throwing.

What the trait silently skips: lazy loads, select() clauses and transactions

The README's own limitations section is the part worth reading twice. Lazy-loaded relationships are not cached, only eager loads through with() are, so a page that loops over records and touches $post->comments inside the loop gains nothing. Queries that use a select() clause bypass the cache entirely, which means a common optimisation habit quietly disables the feature on those queries. Queries inside a transaction are not flushed when the transaction commits, and the README says to call flushCache() manually in that case. inRandomOrder() disables caching by design, which is sensible. The cache driver list is narrower than Laravel's own: Redis, Memcached, APC and DynamoDB are marked supported, while array, file and database drivers are not. That rules out the default file driver many local setups use and the database driver some production deployments prefer, so the package effectively requires an external cache service. There is also the User-model caveat: the trait does not conflict with authentication, but the README advises against cache cool-down periods on it and requires that user updates go through Eloquent rather than raw DB::table() calls. That last point generalises. Any write path outside Eloquent leaves stale entries behind, and the package has no way to detect them.

Compared with Rennokki/Laravel-eloquent-query-cache and Laravel's response cache

The related searches around this package name two neighbours. Rennokki/Laravel-eloquent-query-cache also caches Eloquent queries, but its model is query-level: you opt queries into caching, which keeps the cache surface explicit and narrow. laravel-model-caching inverts that by opting the whole model in through a trait and invalidating on model events, so coverage is broader and per-query control is weaker. If you want to cache three expensive queries and nothing else, the explicit approach is easier to reason about. If you want every read on a model cached without touching call sites, the trait wins. Laravel's response cache sits at a different layer entirely: it caches the rendered HTTP response, so it never sees your query shapes and cannot help with a page whose output varies per user or per request parameter. It also does not invalidate on model writes the way this package does. The three are not mutually exclusive, but stacking a response cache on top of a model cache means a stale response can hide a correctly invalidated query cache, which makes debugging harder than either layer alone.

Maintenance, versioning and the MIT licence

The repository is not archived and the last push was on 2026-09-24, four days before this writing, so the project is being worked on. Recent releases are close together: 13.1.11 on 2026-09-19, 13.1.10 on 2026-09-09 and 13.1.9 on 2026-09-04. The README states requirements of PHP 8.2 or newer and Laravel 12 or 13, and badges on the page list PHP 8.2 through 8.5 and Laravel 11, 12 and 13, which is a small inconsistency between the badge and the requirements section. The version numbering tracks Laravel majors, so moving from Laravel 12 to 13 is likely to mean a major bump of this package too. The README has an Upgrading section in its table of contents, but the text supplied here does not include its contents, so the upgrade path is not something to assume. The licence is MIT, which permits commercial use and modification; the package ships a LICENSE file and the README links to it. This is a description of the licence, not legal advice, and the usual caveat applies that your own compliance review is the authority on what your organisation can ship.

Editorial conclusion

Adopt it if you run Laravel 12 or 13 on PHP 8.2 or newer, your reads outnumber writes, and you already operate Redis or Memcached. Skip it if your hot paths are lazy-loaded relations, select() projections, or code inside transactions, because those bypass the cache or need a manual flushCache() call. Before rollout, confirm your cache store is not file, array, or database, decide whether MODEL_CACHE_USE_DATABASE_KEYING should stay true for your tenant setup, and check whether any writes go through DB::table() rather than Eloquent, since those will not invalidate anything.

Frequently asked questions

How does laravel-model-caching handle caching for Eloquent models?

You add the Cachable trait to a model or a shared base model, and the package caches query results for that model, including aggregations and eager-loaded relationships, flushing the relevant entries when the model is created, updated or deleted.

Is caching with laravel-model-caching good or bad?

The package's own framing is that it helps when an application makes many repeated Eloquent queries on read-heavy pages, and the README lists cases where it does not apply, such as lazy-loaded relations, select() clauses and queries inside transactions. Whether it helps depends on how much of your read path falls inside the supported query shapes.

Which cache drivers does laravel-model-caching support?

The README marks Redis, Memcached, APC and DynamoDB as supported, with Redis recommended, and marks the array, file and database drivers as unsupported. The active store is chosen through the store config key or the MODEL_CACHE_STORE environment variable.

Can I use laravel-model-caching on the User model?

Yes. The README says the Cachable trait does not conflict with Laravel's authentication, but advises against cache cool-down periods on the User model and requires that user updates go through Eloquent rather than raw DB::table() queries so invalidation fires.

What happens to laravel-model-caching when the cache backend goes down?

By default an unavailable cache backend causes an exception. Setting MODEL_CACHE_FALLBACK_TO_DB to true makes the package fall back to direct database queries instead, according to the README's environment variable table.

Official sources

  1. Issues
  2. License: MIT
  3. mike-bronner/laravel-model-caching on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mike-bronner-laravel-model-caching.svg)](https://hysenlabs.com/projects/mike-bronner-laravel-model-caching)