Open-source project
spatie/laravel-responsecache avatar
spatie/laravel-responsecache

spatie/laravel-responsecache: full-response caching for Laravel apps

Speed up a Laravel app by caching the entire response

2,816 stars247 forksPHPMIT

At a glance

What is it?
The package stores complete HTTP responses, HTML and JSON, and serves them without booting the application. It suits read-heavy Laravel sites and fits badly around per-user content unless you configure the cache profile.
Who is it for?
Adopt spatie/laravel-responsecache when most of your traffic is anonymous GET requests for HTML or JSON and the application work behind those routes is expensive. Do not adopt it for routes whose output depends on the authenticated user, on session state, or on data that changes between requests, unless you change the cache profile and the middleware parameters to match.
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 40 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 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What full-response caching buys a Laravel application

Laravel renders a page by running middleware, resolving route model bindings, querying the database, and compiling Blade templates. On a read-heavy route such as a blog index or a public JSON endpoint, that work repeats identically for every visitor. spatie/laravel-responsecache takes the finished response, stores it, and returns the stored copy on the next identical request. The README states that the cached response is returned "without going through the entire application", which is the actual saving: the framework boot and the query layer are skipped, not just the view rendering.

The audience is Laravel developers running public pages that change rarely relative to how often they are read. Documentation sites, marketing pages, category listings, and read-only APIs are the obvious fits. The default behaviour is broad: according to the README, the package caches all successful GET requests that return text-based content such as HTML and JSON, for a week. That default is a starting point rather than a policy, and the rest of this article is largely about narrowing it.

How the middleware, cache profile and stored response fit together

The unit of work is the middleware. You attach it to a route or a route group, and the package decides whether the incoming request is cacheable, looks for a stored response, and either returns it or lets the request continue and saves what comes back. The README describes exactly this order: on the first request the response is saved before being sent to the user, and on a repeat request the stored response is returned.

What gets stored and how it is identified is the cache profile. That is the part worth reading in the documentation before you enable the package globally, because it is where the decision about per-user variation lives. A full-response cache keyed only by URL will hand one visitor's page to another. The package exposes a profile configuration for this reason, and the docs are the place to confirm the current shape of it.

The second mechanism is flexible caching, which the README introduces as an option "for pages where brief staleness is acceptable". After the lifetime expires, the stale response is still served while the cache refreshes in the background. Once the grace period ends, the next request is fully recalculated. That trade is explicit in the API: you pass a lifetime and a grace window, and you accept serving content that is known to be out of date for the length of the grace period.

Installing spatie/laravel-responsecache and caching a first route

The README does not print install commands, so the entry point is the documentation site it links to, spatie.be/docs/laravel-responsecache, and the package on Packagist under the name spatie/laravel-responsecache. Composer is the install path for a Laravel package, and the repository ships a config/ directory, which is the usual signal that the package publishes a configuration file. Confirm the exact publish tag in the documentation before running anything.

The README's own example is the shortest route to a working setup. It applies the middleware to a group of GET routes and gives the cached copy a ten-minute lifetime:

php
use Spatie\ResponseCache\Middlewares\CacheResponse;

Route::middleware(CacheResponse::for(minutes(10)))->group(function () {
    Route::get('/posts', [PostController::class, 'index']);
    Route::get('/posts/{post}', [PostController::class, 'show']);
});

With that in place, the first request to /posts runs the controller normally and the response is stored. A second request to the same URL should be served from the cache, and you can confirm the difference by watching your query log or your debug toolbar rather than by timing the page.

For a dashboard where a slightly stale page is acceptable, the README shows the flexible variant, which takes a lifetime and a grace window as named arguments:

php
use Spatie\ResponseCache\Middlewares\FlexibleCacheResponse;

Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware(FlexibleCacheResponse::for(lifetime: hours(1), grace: minutes(5)));

Here the entry is fresh for an hour. After that it is served stale for up to five minutes while a refresh happens in the background, and only after the grace window does a request pay the full cost again.

Where a full-response cache is the wrong tool

The failure mode is content that varies by viewer. A page that greets the logged-in user by name, a cart count in the header, a CSRF token embedded in a form, or an admin route behind authentication will all be wrong if the response is keyed only by URL and served to the next visitor. The package's default of caching successful GET requests returning HTML and JSON makes this easy to trigger accidentally, because a personalised page is still a successful HTML GET request.

The mitigation is the cache profile plus per-route middleware, not a global switch. If your application is mostly authenticated dashboards, the honest answer is that full-response caching addresses a small share of your traffic, and you should be looking at query caching or fragment caching instead. The same applies to routes that must reflect a write immediately: a checkout confirmation or an order status page should not sit behind a ten-minute cache.

The flexible mode has its own boundary. Serving a stale response during the grace window is a deliberate correctness trade, and the README frames it as suitable for pages where brief staleness is acceptable. If a page cannot tolerate being five minutes behind, flexible caching is not the right middleware for it, regardless of how much load it would remove.

Response caching compared with a reverse proxy such as Varnish

The repository's topics list Varnish alongside cache, laravel, performance and php, which is a fair pointer to the alternative. Varnish sits in front of the application as a separate HTTP accelerator. It never reaches PHP on a cache hit, so it removes the web server and framework cost entirely, and it handles cache invalidation through its own configuration language. The cost is operational: another service to run, a configuration language to learn, and a purge strategy to design.

spatie/laravel-responsecache runs inside the application. A hit still boots Laravel far enough to run the middleware, which means you do not get the full saving a proxy gives you. What you get instead is that the cache lives next to the code: routes opt in through middleware, and invalidation can be triggered from application code and from Artisan. For a team that already deploys Laravel and does not want a second caching tier, that is the trade. If you already run Varnish or a CDN with origin caching, adding this package on top duplicates the job and creates two places where a stale page can come from.

Maintenance, upgrades and the MIT licence

The repository is not archived, and the last push was on 2026-08-20. Releases in the 8.x line have continued through 2026, with 8.4.3 on 2026-08-07. That is a maintained package by the only measure available here, though the cadence of releases is not the same thing as a support commitment.

Upgrade cost is real for a package that touches every cached route. The repository carries an UPGRADING.md at the top level, which is where breaking changes between major versions are recorded, and the README example already uses the current middleware API where the lifetime is passed to CacheResponse::for(...) rather than set globally. If you are on an older major version, read UPGRADING.md before bumping, because middleware signatures are exactly the kind of thing that changes across majors.

The licence is MIT, per the README and the LICENSE.md file in the repository. That permits commercial use and modification, with the usual requirement to keep the copyright notice. This is a description of the licence text, not legal advice; if your organisation has rules about bundled dependencies, route it through whoever normally reviews them.

Editorial conclusion

Adopt spatie/laravel-responsecache when most of your traffic is anonymous GET requests for HTML or JSON and the application work behind those routes is expensive. Do not adopt it for routes whose output depends on the authenticated user, on session state, or on data that changes between requests, unless you change the cache profile and the middleware parameters to match. Before rolling it out, verify three things on a staging environment: which routes actually receive the middleware, what the cache profile does with the authenticated user, and how you will invalidate entries after a content change. The package ships a config file and an Artisan command for that last point, so the invalidation path is testable rather than theoretical.

Frequently asked questions

How do I clear the cache in spatie/laravel-responsecache?

The repository ships an Artisan command for invalidation, and the documentation site describes the available commands. Check the documentation for the exact command name in your installed version before relying on it in a deploy script.

How can I use Redis with spatie/laravel-responsecache?

The package stores responses through Laravel's cache layer, so the backing store is chosen in your application's cache configuration rather than in the package itself. The README does not document a Redis-specific setup.

Does spatie/laravel-responsecache cache every route automatically?

No. Caching is opt-in per route or route group through the CacheResponse middleware, as shown in the README example. The default lifetime and the set of cacheable requests apply once the middleware is attached.

What is the difference between CacheResponse and FlexibleCacheResponse in spatie/laravel-responsecache?

CacheResponse serves the stored response until its lifetime expires. FlexibleCacheResponse, per the README, keeps serving the stale response instantly after the lifetime expires while refreshing in the background, until the grace period ends.

Is spatie/laravel-responsecache suitable for pages behind a login?

Not with the default setup. A full-response cache keyed by URL will serve one visitor's page to another, so personalised routes need a cache profile that accounts for the authenticated user, or they should not carry the middleware at all.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. spatie/laravel-responsecache on GitHub
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/spatie-laravel-responsecache.svg)](https://hysenlabs.com/projects/spatie-laravel-responsecache)