Learn how to implement database query caching in Laravel to reduce server load. Master cache eviction strategies to ensure data integrity in high-traffic apps.
Previously in this course, we explored Database Indexing Strategies: Optimizing Laravel Query Performance. While indexing is your first line of defense against slow queries, even the most optimized B-Tree index cannot save you from an expensive, repetitive query hitting the database millions of times per day. This lesson adds a layer of intelligence to your data access by implementing caching at the query level.
Database query caching is the act of storing the result set of an expensive SQL operation in a fast, in-memory key-value store (like Redis or Memcached). Instead of asking the database to perform the same heavy computation—such as complex aggregations or deep relationship loading—your application checks the cache first.
Think of it as a two-tier lookup:
In Laravel, we leverage the remember() method on the Query Builder or Eloquent. This is the cleanest way to wrap execution logic without cluttering your services.
Imagine our SaaS platform has a dashboard widget showing the "Top 100 Revenue-Generating Customers" over the last 30 days. This involves complex joins and sum calculations.
PHPnamespace App\Services\Billing; use App\Models\Customer; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; class RevenueService { public function getTopCustomers(int $days = 30) { $cacheKey = "top_customers_last_{$days}_days"; return Cache::remember($cacheKey, now()->addMinutes(60), function () use ($days) { return Customer::query() ->select('customers.*') ->join('orders', 'customers.id', '=', 'orders.customer_id') ->where('orders.created_at', '>=', now()->subDays($days)) ->groupBy('customers.id') ->orderByRaw('SUM(orders.amount) DESC') ->limit(100) ->get(); }); } }
By adding this layer, we shift the burden from the database CPU to the Redis memory. The query only hits the database once per hour, regardless of how many thousands of users load the dashboard.
The biggest risk with caching is "stale data." If a customer updates their profile or a new order is placed, your cache will still serve the old, cached result until the TTL expires. You must implement proactive cache eviction.
The most robust approach is to tie cache clearing to model events.
PHP#6A9955">// In your Service Provider or a dedicated Listener Customer::updated(function ($customer) { Cache::forget("top_customers_last_30_days"); });
For more complex scenarios where multiple queries depend on the same dataset, consider using Cache Tags (if using Redis or Memcached) to flush groups of related queries at once.
Billing or Reporting domain.Cache::remember() with a 15-minute TTL.DB::listen) and checking if the logs stop appearing on subsequent page refreshes.Database query caching is a powerful tool to scale your SaaS, but it requires discipline. By wrapping your most expensive SQL queries in Cache::remember() and meticulously managing eviction via model events, you significantly reduce the load on your primary database. Always prioritize indexing first, as shown in our earlier modules on PostgreSQL Indexing: B-Tree vs GIN for Better Query Performance, and use caching as your second-tier optimization.
Up next: We will dive into Advanced Eloquent Scopes to make these complex queries reusable and maintainable across your domain services.
Master SQL indexing for joins by learning to analyze execution plans and build covering indexes that eliminate table scans in high-traffic Laravel applications.
Read moreScale your database capacity by offloading heavy read traffic to replicas. Learn how to configure Laravel to automatically route read/write database queries.
Database Query Caching Layers
Custom Middleware Development
Database Connection Pooling
Handling Large Data Exports
Security Header Configuration
Database Sharding Concepts
Real-time Data Synchronization
Database Deadlock Prevention
Managing Third-Party API Integrations