Back to Blog
    Laravel 13 cachingLaravel Redis cacheLaravel cache driversLaravel Cache::rememberLaravel performance optimizationLaravel 13LaravelPHPRedisCachingPerformance

    Laravel 13 Caching: Redis, Cache Drivers & Real-World Examples

    Learn Laravel 13 caching with Redis, cache drivers, Cache::remember(), TTLs, cache invalidation, atomic locks, and practical production examples.

    2026-09-09 · Abhilash Raj · 14 min read

    Laravel 13 Caching: Redis, Cache Drivers & Real-World Examples

    Laravel 13 Caching: Redis, Cache Drivers & Real-World Examples

    A fast Laravel application is not only about writing efficient database queries. As an application grows, repeatedly executing the same expensive queries, API requests, calculations, and configuration lookups can become a major performance bottleneck.

    This is where caching becomes extremely useful.

    Laravel 13 provides a powerful caching system that allows developers to store frequently used data and retrieve it quickly without repeating expensive operations. You can use simple file or database caching for smaller applications, or Redis for high-performance production workloads.

    In this guide, you'll learn how Laravel 13 caching works, how to use Cache::remember(), how Redis fits into Laravel, how to choose a cache driver, and how to design a practical caching strategy for production applications.


    What Is Caching?

    Caching means temporarily storing data that is expensive or slow to generate so that it can be reused later.

    Consider a dashboard that executes several database queries every time a user opens it.

    Without caching:

    User Request
         ↓
    Laravel Application
         ↓
    Database Queries
         ↓
    Process Data
         ↓
    Return Response
    

    If thousands of users request the same information, the application may repeatedly execute the same queries.

    With caching:

    User Request
         ↓
    Laravel Application
         ↓
    Check Cache
       ↙       ↘
    Hit         Miss
     ↓           ↓
    Return     Database
    Data       Query
                  ↓
               Store Cache
                  ↓
              Return Data
    

    The second request can often avoid the expensive database operation completely.

    Caching can therefore help reduce:

    • Database load
    • API requests
    • CPU usage
    • Response time
    • Server resource consumption

    Laravel 13 Cache Drivers

    Laravel provides a consistent cache API while allowing you to choose different storage backends.

    Depending on your application and environment, you can use cache stores such as:

    • Database
    • File
    • Redis
    • Memcached
    • Array
    • Null
    • Other supported stores

    The important advantage is that your application code can use Laravel's Cache API without being tightly coupled to one storage system.

    For example:

    use Illuminate\Support\Facades\Cache;
    
    $value = Cache::get('homepage.data');
    

    Your application can later move from one cache backend to another with relatively little application-code change.


    Configuring the Cache Store

    Laravel's cache configuration is controlled through your application's configuration and environment variables.

    For example:

    CACHE_STORE=database
    

    For a Redis-based production environment:

    CACHE_STORE=redis
    

    The exact environment configuration can vary depending on how Redis is installed and configured on your server.

    After changing configuration values in production, remember to clear and rebuild your Laravel configuration cache when appropriate:

    php artisan config:clear
    php artisan config:cache
    

    Basic Laravel Cache Usage

    The Cache facade provides simple methods for storing and retrieving values.

    Store a Value

    use Illuminate\Support\Facades\Cache;
    
    Cache::put('site.name', 'Abhilash Raj', 3600);
    

    The third argument represents the cache lifetime in seconds.

    In this example, the value is cached for one hour.


    Retrieve a Value

    $name = Cache::get('site.name');
    

    You can also provide a default value:

    $name = Cache::get('site.name', 'Guest');
    

    Check Whether a Key Exists

    if (Cache::has('site.name')) {
        // Cache exists
    }
    

    Remove Cached Data

    Cache::forget('site.name');
    

    The Most Useful Method: Cache::remember()

    One of the most useful Laravel caching patterns is:

    Cache::remember()
    

    Instead of manually checking whether data exists, Laravel can retrieve the cached value or execute a callback when the value is missing.

    For example:

    $posts = Cache::remember(
        'popular-posts',
        3600,
        function () {
            return Post::where('views', '>', 1000)
                ->latest()
                ->take(10)
                ->get();
        }
    );
    

    The process works like this:

    Cache exists?
          │
     ┌────┴────┐
     Yes       No
     │          │
    Return    Execute Query
    Data        │
                ↓
            Store Result
                │
                ↓
            Return Data
    

    This is much cleaner than manually writing cache lookup logic.

    Laravel's cache repository exposes remember() specifically for retrieving an item or executing a callback and storing its result when the item is not already cached.


    Real-World Example: Caching a Dashboard

    Imagine your admin dashboard displays:

    • Total users
    • Total orders
    • Revenue
    • Recent transactions
    • Popular products

    Some of these values don't need to be calculated on every request.

    Instead of:

    $totalUsers = User::count();
    
    $totalOrders = Order::count();
    
    $totalRevenue = Order::sum('total');
    

    you could cache them:

    $totalUsers = Cache::remember(
        'dashboard.total_users',
        300,
        fn () => User::count()
    );
    
    $totalOrders = Cache::remember(
        'dashboard.total_orders',
        300,
        fn () => Order::count()
    );
    
    $totalRevenue = Cache::remember(
        'dashboard.total_revenue',
        300,
        fn () => Order::sum('total')
    );
    

    Now those expensive calculations are reused for five minutes.


    Choosing the Right Cache Duration

    There is no universal TTL that works for every piece of data.

    A good rule is:

    DataExample TTL
    Frequently changing data30–60 seconds
    Dashboard statistics5 minutes
    Product catalog10–30 minutes
    Categories1 hour
    Configuration-like dataSeveral hours
    Rarely changing content1 day
    Static reference dataLonger

    The correct TTL depends on how frequently your underlying data changes and how stale the application can safely allow the result to become.


    Cache Keys Matter

    A good cache key should be:

    • Unique
    • Predictable
    • Descriptive
    • Easy to invalidate

    Avoid:

    Cache::remember('data', 3600, ...);
    

    Prefer:

    Cache::remember('products.popular', 3600, ...);
    

    For user-specific data:

    Cache::remember(
        'user.' . $user->id . '.dashboard',
        600,
        fn () => $this->buildDashboard($user)
    );
    

    For parameterized queries:

    $key = "products.category.{$categoryId}.page.{$page}";
    
    $products = Cache::remember(
        $key,
        600,
        fn () => Product::where('category_id', $categoryId)
            ->paginate(20)
    );
    

    This prevents different users or requests from accidentally sharing the wrong cached result.


    Redis and Laravel 13

    For many production Laravel applications, Redis is an excellent cache backend.

    Redis is an in-memory data store designed for very fast data operations.

    Laravel's Redis documentation recommends PhpRedis and also supports Predis when the PHP extension isn't available.

    A typical environment might contain:

    REDIS_CLIENT=phpredis
    
    REDIS_HOST=127.0.0.1
    REDIS_PASSWORD=null
    REDIS_PORT=6379
    

    Then your cache store can use Redis:

    CACHE_STORE=redis
    

    The exact values will depend on your Redis installation and hosting environment.


    PhpRedis vs Predis

    Laravel supports two common Redis clients.

    PhpRedis

    PhpRedis is a PHP extension.

    It is generally a good choice when you control your server and can install PHP extensions.

    Laravel's Redis documentation recommends using PhpRedis and notes that it may provide better performance for applications making heavy use of Redis.

    Predis

    Predis is a PHP package that doesn't require the PhpRedis extension.

    Install it with:

    composer require predis/predis
    

    This can be useful when you don't have permission or ability to install PHP extensions.


    Caching Eloquent Queries

    Caching database results is one of the easiest ways to improve application performance.

    For example:

    $categories = Cache::remember(
        'categories.all',
        3600,
        fn () => Category::orderBy('name')->get()
    );
    

    Instead of running:

    SELECT * FROM categories ORDER BY name;
    

    on every request, Laravel can retrieve the result from the cache.

    This is especially useful for data such as:

    • Categories
    • Countries
    • States
    • Navigation menus
    • Popular posts
    • Product lists
    • Settings
    • Frequently requested reports

    Cache Expensive API Requests

    Caching isn't limited to database queries.

    Suppose your application calls an external API:

    $response = Http::get('https://example.com/api/products');
    

    Repeated API requests can increase:

    • API costs
    • Network traffic
    • Response time
    • Dependency on third-party services

    You can cache the result:

    $products = Cache::remember(
        'external.products',
        900,
        function () {
            return Http::get(
                'https://example.com/api/products'
            )->json();
        }
    );
    

    Now the external API is called only when the cached value expires or is removed.


    Cache Invalidation

    One of the most important caching concepts is cache invalidation.

    Imagine you cache a product:

    $product = Cache::remember(
        "product.{$id}",
        3600,
        fn () => Product::findOrFail($id)
    );
    

    Then an administrator updates the product.

    The database contains the new information, but the cache may still contain the old version.

    You can explicitly remove it:

    Cache::forget("product.{$id}");
    

    Then the next request retrieves the updated product from the database and stores it again.


    Cache Invalidation After Model Updates

    A common approach is to clear related cache entries after updating a model.

    For example:

    $product->update($data);
    
    Cache::forget("product.{$product->id}");
    

    For more complex applications, you can centralize this logic using model observers, events, services, or dedicated cache-management classes.

    The important principle is:

    Whenever important data changes, decide which cached representations are no longer valid.


    Avoid Caching Everything

    Caching is powerful, but caching every query is usually a mistake.

    Don't automatically cache:

    • Highly dynamic data
    • Frequently changing records
    • User-specific sensitive data without careful key design
    • Data where stale information could cause financial or business problems
    • Very cheap queries where caching adds more complexity than value

    For example, caching a simple query that takes 1 ms may not provide meaningful benefits.

    Instead, focus on operations that are:

    • Expensive
    • Repeated frequently
    • Stable for a period of time
    • Expensive to calculate
    • Dependent on external services

    Cache Tags

    Some cache stores support cache tags, which can help organize related cached items.

    For example:

    Cache::tags(['products'])->put(
        'popular',
        $products,
        3600
    );
    

    You can then flush the related cache entries:

    Cache::tags(['products'])->flush();
    

    This can be useful when a particular group of cached data needs to be invalidated together.

    Before relying on tags, verify that the selected cache driver supports the features you need.


    Laravel Cache Atomic Locks

    Caching can also be used for distributed locking.

    Suppose two workers attempt to process the same operation at the same time.

    You can use an atomic lock:

    $lock = Cache::lock('process-report', 120);
    
    if ($lock->get()) {
        try {
            // Perform the operation
        } finally {
            $lock->release();
        }
    }
    

    This can help prevent duplicate work in distributed applications.

    Laravel's cache system provides atomic lock support, and the lock is especially useful when multiple processes or servers need to coordinate access to a shared operation.


    Preventing Duplicate Expensive Calculations

    Consider a report that takes 30 seconds to generate.

    If 50 users request the same report simultaneously, you don't want 50 processes generating the same result.

    A lock can help coordinate the work.

    Conceptually:

    50 Requests
         ↓
    Acquire Lock
         ↓
    One request generates report
         ↓
    Cache result
         ↓
    Other requests use cached result
    

    This pattern can dramatically reduce unnecessary server work.


    Laravel 13 Flexible Caching

    Laravel 13 also exposes the flexible() cache API, which supports a stale-while-revalidate style approach.

    The basic idea is:

    $value = Cache::flexible(
        'popular.products',
        [60, 300],
        function () {
            return Product::popular()->get();
        }
    );
    

    This approach can allow applications to serve a recently cached value while refreshing stale data in the background, depending on the configured behavior.

    Laravel's current cache API documents flexible() alongside remember(), rememberForever(), and touch().

    This can be particularly useful for high-traffic pages where you want to avoid making users wait for a full cache regeneration.


    Cache::touch()

    Laravel 13 also provides:

    Cache::touch(...)
    

    This allows an existing cache item's TTL to be extended without retrieving and storing the complete value again.

    For applications with more advanced cache lifecycle requirements, this can simplify TTL management.


    Caching Configuration

    Laravel configuration is commonly cached during deployment:

    php artisan config:cache
    

    This creates a cached configuration representation that Laravel can load efficiently.

    When changing environment variables in production, make sure the application configuration cache is refreshed.

    A typical deployment sequence might include:

    php artisan optimize:clear
    php artisan config:cache
    php artisan route:cache
    php artisan view:cache
    

    Only use the commands appropriate for your deployment process.


    Redis for High-Traffic Applications

    As your application grows, Redis becomes increasingly useful because it can serve more than just application cache.

    A Laravel application may use Redis for:

    • Cache
    • Queues
    • Rate limiting
    • Locks
    • Sessions
    • Temporary data
    • Counters
    • Pub/Sub
    • Application-specific data structures

    Laravel's Redis integration supports multiple Redis connections, clustering, transactions, and pipelining.

    This makes Redis a useful building block for scalable Laravel applications.


    Example: High-Traffic Blog

    Imagine your Laravel blog has 100,000 visitors per day.

    Your homepage displays:

    • Latest articles
    • Popular articles
    • Categories
    • Trending posts

    Without caching, every request could trigger multiple database queries.

    A better approach is:

    $latest = Cache::remember(
        'blog.latest',
        300,
        fn () => Post::published()
            ->latest('published_at')
            ->take(10)
            ->get()
    );
    
    $popular = Cache::remember(
        'blog.popular',
        600,
        fn () => Post::published()
            ->orderByDesc('views')
            ->take(10)
            ->get()
    );
    

    The database doesn't need to calculate the same result for every visitor.


    Example: Caching API Data

    For an API endpoint:

    public function index()
    {
        $users = Cache::remember(
            'api.users',
            300,
            fn () => User::select(
                'id',
                'name',
                'email'
            )->latest()->get()
        );
    
        return response()->json($users);
    }
    

    This can significantly reduce database activity when the endpoint receives repeated requests.


    Example: User-Specific Cache

    Be careful when caching data that belongs to individual users.

    Bad:

    Cache::remember('dashboard', 600, function () {
        return auth()->user()->orders;
    });
    

    This could cause users to receive the wrong cached data because every user shares the same key.

    Instead:

    $userId = auth()->id();
    
    $orders = Cache::remember(
        "user.{$userId}.orders",
        600,
        fn () => auth()->user()->orders
    );
    

    The cache key now contains the user identifier.

    This is an important security and correctness consideration.


    Cache Key Versioning

    Sometimes you change the structure of cached data.

    Instead of:

    'products.popular'
    

    you can use:

    'v2.products.popular'
    

    This provides a simple way to invalidate an old cache namespace without manually deleting every old key.

    For larger systems, versioned keys can make deployments safer.


    Don't Cache Sensitive Information Carelessly

    Caching private information requires careful consideration.

    Be especially careful with:

    • Authentication data
    • Payment information
    • Personal information
    • Private API responses
    • Authorization results
    • User-specific dashboards

    If sensitive information must be cached, use appropriately scoped cache keys, secure infrastructure, suitable TTLs, and access controls.


    Redis Production Checklist

    If you're deploying Laravel with Redis in production, check the following:

    • Redis is protected from public internet access
    • Authentication is configured where appropriate
    • Firewall rules are restrictive
    • Redis uses appropriate memory limits
    • Eviction behavior is understood
    • Applications use meaningful key prefixes
    • Cache TTLs are defined
    • Sensitive information is handled carefully
    • Redis monitoring is configured
    • Backups are considered where Redis stores persistent application data
    • Application and Redis servers have appropriate network connectivity

    Laravel's Redis configuration supports connection details such as host, port, username, password, database, and connection options.


    Common Laravel Caching Mistakes

    1. Using extremely long TTLs

    A cache that never expires can eventually become stale.

    Prefer a deliberate TTL unless permanent caching is genuinely required.


    2. Forgetting cache invalidation

    Updating the database doesn't automatically mean every related cache entry becomes invalid.

    Plan invalidation when designing the feature.


    3. Using generic cache keys

    Avoid:

    'data'
    

    Prefer:

    'products.featured'
    

    4. Sharing user-specific cache

    Always include the appropriate user or tenant identifier.


    5. Caching everything

    Caching adds complexity.

    Cache data where the performance benefit justifies the additional lifecycle management.


    6. Using Redis without monitoring

    Redis is fast, but production systems still need monitoring and capacity planning.


    A Practical Laravel Caching Strategy

    For a typical Laravel production application, I recommend starting with this approach:

    Step 1 — Identify expensive operations

    Find:

    • Slow database queries
    • Repeated API requests
    • Expensive calculations
    • Large datasets
    • Frequently requested pages

    Step 2 — Measure first

    Use application monitoring and database profiling to identify actual bottlenecks.

    Step 3 — Add targeted caching

    Start with:

    Cache::remember()
    

    rather than introducing complicated caching architecture immediately.

    Step 4 — Choose an appropriate TTL

    Ask:

    How stale can this data safely be?

    Then choose the TTL accordingly.

    Step 5 — Design invalidation

    Determine what happens when the underlying data changes.

    Step 6 — Move to Redis when appropriate

    Redis is an excellent choice when your application needs fast centralized caching across multiple workers or servers.


    Useful Laravel Cache Commands

    You can inspect available Artisan commands with:

    php artisan list
    

    For clearing application caches during deployment or troubleshooting:

    php artisan optimize:clear
    

    Then rebuild the caches required by your production deployment:

    php artisan config:cache
    php artisan route:cache
    php artisan view:cache
    

    Always test your deployment workflow in your own environment before applying it automatically to production.


    Laravel 13 Caching Best Practices

    Here is a practical checklist:

    • Use Cache::remember() for repeated expensive operations.
    • Use meaningful cache keys.
    • Choose TTLs based on how frequently data changes.
    • Invalidate cache when important underlying data changes.
    • Use Redis for high-performance centralized caching.
    • Keep user-specific data isolated by cache key.
    • Don't cache everything.
    • Monitor Redis memory and performance.
    • Protect Redis from public access.
    • Use atomic locks when multiple workers can perform the same operation.
    • Consider stale-while-revalidate patterns for high-traffic content.
    • Test cache behavior after deployments.
    • Measure performance before and after introducing caching.

    Conclusion

    Caching is one of the most effective ways to improve a Laravel application's performance when it is applied strategically.

    Laravel 13 provides a clean caching API that lets you start with simple methods such as:

    Cache::remember()
    

    and scale toward more advanced solutions using Redis, atomic locks, flexible caching, and distributed application architectures.

    The key isn't to cache everything.

    The goal is to identify expensive operations that happen repeatedly, cache the right data for the right amount of time, and build a reliable invalidation strategy.

    For most production Laravel applications, a combination of efficient database queries + targeted caching + Redis + proper cache invalidation can provide a strong foundation for performance and scalability.


    Continue Learning

    If you're optimizing a Laravel 13 application, these related guides are useful next steps:

    Together, these techniques cover some of the most important areas of Laravel application performance: database optimization, caching, background jobs, and production deployment.

    Advertisement

    Share this post

    Comments

    Loading comments...

    Related articles

    Follow new notes

    Use the RSS feed in your reader. For questions, start a WhatsApp conversation.

    RSS feed