
September 12, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
Your app feels fast in staging and crawls under real traffic. The fix is rarely a bigger server. Caching Strategies: A Practical Guide starts with one question: where does repeated work happen, and who should store the result? On production Laravel apps I maintain, the answer spans browser caches, CDN edges, reverse proxies, Redis, and query memoisation. This page maps those layers, shows copy-paste patterns, and covers invalidation without the usual hand-waving. If you already ship sites, pair this with our web performance caching guide for measurement context.
What Are the Main Caching Layers in a Modern Web Stack?
Every request passes through several decision points before PHP runs. Each layer can answer without hitting your app. That is the whole point of layered caching.
Start at the browser. Static assets with long Cache-Control headers load instantly on repeat visits. A CDN sits in front of your origin and stores HTML fragments, images, and API responses at edge nodes. Nginx or Varnish can cache full pages or micro-cache hot URLs. Inside Laravel, Redis holds config, routes, views, sessions, and computed aggregates. MySQL query cache is gone, but application-level query result caching still cuts database load sharply.
Browser and CDN caching
Public assets belong on long TTLs. Fingerprinted files from Vite 8.x can use Cache-Control: public, max-age=31536000, immutable. HTML and JSON usually need shorter TTLs or no-cache with revalidation. CDNs honour the same headers your origin sends. Misconfigured headers are a common cause of stale content or zero cache hit rate.
Reverse proxy and application cache
Nginx proxy_cache or Varnish can serve anonymous page shells in milliseconds. See our Varnish reverse-proxy caching guide for VCL patterns. Laravel talks to Redis 8.10 through the cache facade. That is where config, route, view, and data caches live in production.
How Do You Choose the Right Caching Strategy for Each Workload?
Not everything should be cached. The decision tree is simple once you classify the data.
- Immutable reference data — countries, tax rates, category trees. Long TTL, tag invalidation on admin update.
- Aggregates and dashboards — order counts, report summaries. Short TTL (60–300 seconds) or event-driven refresh.
- User-specific views — cart, notifications, portal dashboards. Cache per user ID with narrow keys; purge on write.
- Search and filters — cache keyed by query hash; invalidate when underlying records change.
- Never cache — payment callbacks, CSRF tokens, one-time codes, personalised legal documents.
| Layer | Best for | Typical TTL | Invalidation |
|---|---|---|---|
| Browser | CSS, JS, fonts, images | 1 year (hashed) | New build hash |
| CDN | Public HTML, API GET | 5 min – 24 hr | Cache purge API |
| Reverse proxy | Anonymous pages | 30 sec – 5 min | Purge + TTL expiry |
| Redis (app) | Config, queries, counts | 1 min – 1 hr | Tags, events, TTL |
| Database | Heavy read reports | Session / materialised | Refresh job |
On booking systems like Adventure Third Pole Trek, availability slots change often. A 30-second Redis cache beats a five-minute CDN cache for inventory pages. Marketing landing pages on the same site can sit on the CDN for hours.
How Should You Implement Application-Level Caching in Laravel?
Laravel 13.x (PHP 8.3+) ships with a unified cache API. Point CACHE_STORE=redis in .env and run Redis 8.10 on the same VPC as your app servers. I've used this stack on legal-tech portals and eCommerce builds alike.
Framework caches you should enable in production
- Config cache —
php artisan config:cacheafter deploy. Cuts bootstrap I/O on every request. - Route cache —
php artisan route:cachewhen routes are static. Skip if you rely on closure routes. - View cache —
php artisan view:cacheprecompiles Blade templates. - Event cache —
php artisan event:cacheon Laravel 11+ for faster listener resolution.
These belong in your Deployer 7 post-deploy hook. Reload PHP-FPM after symlink swap so opcache picks up changes. Our Laravel config, route, and view caching guide walks through each command.
Data caching with remember() and tags
Wrap expensive queries in Cache::remember(). Use tags when your Redis driver supports them:
use Illuminate\Support\Facades\Cache;
$categories = Cache::tags(['catalog'])->remember(
'categories:tree',
now()->addHour(),
fn () => Category::with('children')->whereNull('parent_id')->get()
);
// On admin save:
Cache::tags(['catalog'])->flush(); For WooCommerce 11.1 stores or custom Laravel carts, cache product lists separately from stock counts. Stock changes more often than titles or descriptions. Split keys keep hit rates high without serving wrong inventory.
Locking prevents cache stampedes. Laravel's Cache::lock() lets one worker rebuild while others wait:
$data = Cache::remember('report:daily', 300, function () {
return Cache::lock('report:daily:lock', 10)->block(5, function () {
return DB::table('orders')->selectRaw('DATE(created_at), COUNT(*)')
->groupByRaw('DATE(created_at)')->get();
});
}); Refer to the official Laravel 13.x cache documentation for driver configuration and atomic locks.
What Cache Invalidation Patterns Actually Work in Production?
Cache invalidation is the hard part. TTL-only strategies are fine for low-stakes data. Business-critical pages need explicit purge logic.
Event-driven invalidation
Fire a domain event when a model changes. A listener flushes tagged keys or deletes specific entries. On a production Laravel application, I wire ProductUpdated to Cache::tags(['product:'.$id])->flush(). That beats guessing TTL lengths.
Write-through and cache-aside
Cache-aside is the default Laravel pattern: read cache, on miss query DB and store. Write-through updates cache and DB together on every write. Use write-through for hot counters where stale reads hurt revenue. Use cache-aside everywhere else.
HTTP cache headers for edge layers
Set headers in middleware or at the web server. Public blog posts can use:
return response($html)->header('Cache-Control', 'public, max-age=300, s-maxage=600')
->header('Vary', 'Accept-Encoding'); Authenticated portal pages need Cache-Control: private, no-store. The MDN Cache-Control reference documents every directive. Pair header strategy with our reverse-proxy caching setup guide.
Database query caching deserves its own treatment. Read database query caching strategies for Eloquent-specific patterns and N+1 avoidance alongside Redis memoisation.
How Do You Measure, Debug, and Avoid Common Caching Mistakes?
If you cannot measure hit rate, you are guessing. Add logging around cache misses in staging first. Redis INFO stats shows keyspace hits and misses globally.
Metrics that matter
- Hit ratio — target 85%+ for reference data keys; 50–70% is normal for search caches.
- Origin load — PHP-FPM active processes should drop after warm-up.
- p95 latency — compare cached vs uncached routes in your APM.
- Stale incident count — track support tickets tied to old content.
Use the JSON formatter tool to inspect cached API payloads during debugging. Export a key from Redis with redis-cli GET your:key and validate structure before blaming the database.
Mistakes I see repeatedly
Caching the entire HTML output for logged-in users without Vary: Cookie leaks one user's dashboard to another. That is a security bug, not a performance win.
Running php artisan cache:clear in production during peak hours evicts every key at once. Prefer tag flushes scoped to the changed resource.
Storing session data in Redis while also using Redis for cache without separate databases (REDIS_CACHE_DB=1) causes accidental session loss on flush.
High-traffic sites need tiered TTLs. Our high-traffic caching strategies article covers stampede protection and CDN tiering in detail.
Redis data structures beyond plain strings — hashes, sorted sets, HyperLogLog — can replace heavy SQL for leaderboards and unique counts. See Redis caching and data structures for patterns that cut query time without denormalising every table.
CI pipelines benefit from layer caching too. Docker and Composer caches in GitLab CI shave minutes off each build. The CI build caching guide applies the same principles upstream of production.
When cache corruption or bad deploys cause widespread stale content, know your rollback path. Infrastructure rollback strategies pair with dep rollback on Deployer-managed hosts.
API rate limiting often shares Redis with application cache. Read rate limiting strategies for APIs to isolate keys and avoid contention on the same instance.
For WooCommerce-heavy builds like Sagun Blossom Flower, page caching plugins help anonymous traffic. Personalised cart and checkout paths still bypass the cache entirely. Know which plugin toggles affect which routes before enabling full-page cache in production.
Server tuning matters as much as application code. PHP-FPM worker count, Redis maxmemory-policy, and MySQL 9.7 buffer pool size all affect how much headroom you gain from caching. Our Linux system administration service covers Redis and PHP-FPM sizing on Ubuntu 22/24 hosts.
Professional audits catch misconfigured headers and missing warm-up scripts. If you want an outside review, see testing and optimization services or dedicated speed optimization for Core Web Vitals work alongside cache tuning.
The official Redis CLI documentation is the reference for inspecting keys, memory usage, and eviction stats during incidents.
Key Takeaways
- Stack caches bottom-up: browser, CDN, reverse proxy, Redis, then query memoisation — each layer needs its own TTL and purge rules.
- Enable Laravel config, route, view, and event caches on every production deploy; reload PHP-FPM after symlink swap.
- Use tagged invalidation and domain events instead of global
cache:clearduring business hours. - Never cache authenticated HTML at the CDN without correct
Varyheaders; useprivate, no-storefor portals and checkout. - Measure hit ratio and p95 latency per route; warm critical keys after deploy before sending traffic.
- Separate Redis databases for cache, session, and queue to prevent accidental cross-flush.
People Also Ask
What is the difference between cache-aside and write-through caching?
Cache-aside loads data into the cache only on a miss. The application reads Redis first, then the database. Write-through updates both cache and database on every write. Cache-aside is simpler and fits most Laravel read-heavy pages. Write-through suits counters and inventory where stale reads have direct business cost.
How long should cache TTL be?
Match TTL to acceptable staleness. Static assets can live a year with content hashes. Public HTML often uses 5–15 minutes at the CDN. Application aggregates commonly use 60–300 seconds. User-specific data should expire quickly or invalidate on write rather than relying on a long TTL.
Is Redis required for Laravel caching?
No. Laravel supports file, database, Memcached 1.6.x, and array drivers. Redis is the production default because it is fast, supports tags on recent drivers, and doubles as session and queue storage. File cache works on small shared hosts but does not scale across multiple app servers.
How do you clear CDN cache after a deployment?
Call your CDN provider's purge API from the deploy pipeline. Purge changed URL paths or cache tags rather than full-zone flush when possible. Warm critical URLs with HTTP requests immediately after purge so the first real user does not pay the cold-cache penalty.
Ship Caching That Survives Production Traffic
Caching Strategies: A Practical Guide is not a one-time config change. It is a lifecycle: classify data, pick the right layer, invalidate on events, measure hit rate, and roll back when something goes wrong. Start with Laravel framework caches and Redis for your heaviest queries. Add CDN and reverse-proxy rules only after HTTP headers are correct.
If you want help auditing an existing app or designing cache architecture for a new build, review our web development services or enterprise application development offerings. For ongoing tuning after launch, support and maintenance keeps deploy hooks, Redis memory, and CDN purges aligned with your traffic patterns.
Contact us with your stack details — Laravel version, traffic profile, current Redis setup — and we can map a caching plan that fits your budget and team size.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

