paulund

Caching

Caching

Caching sits between your application and its slowest operations — database queries, external API calls, expensive computations. Laravel's cache system is driver-agnostic: the same code works whether you are using files, Redis, Memcached, or a database-backed store.

Cache Drivers

Configure your driver in .env:

CACHE_DRIVER=redis

Common drivers and when to use them:

Driver Best for
file Local development, single-server deployments
redis Production, shared across multiple servers
memcached High-throughput scenarios where you do not need persistence
database Simple deployments where Redis is not available
array Tests — fast, in-memory, cleared between requests
null Disabling the cache entirely (useful in CI)

Basic Operations

use Illuminate\Support\Facades\Cache;

// Store a value for 60 seconds
Cache::put('user:1', $user, 60);

// Retrieve it (returns null if missing)
$user = Cache::get('user:1');

// Retrieve with a default fallback
$user = Cache::get('user:1', 'not found');

// Check if a key exists
if (Cache::has('user:1')) { /* ... */ }

// Remove a key
Cache::forget('user:1');

// Clear the entire cache
Cache::flush();

remember() — The Most Useful Method

remember() combines a get and a put into one call. It fetches the value from cache if it exists; otherwise it runs the closure, stores the result, and returns it:

$categories = Cache::remember('categories', 3600, function () {
    return Category::with('children')->get();
});

Use rememberForever() when the data rarely changes and you plan to invalidate manually:

$settings = Cache::rememberForever('app_settings', function () {
    return Setting::all()->keyBy('key');
});

Cache Tags

Tags let you group related cache entries and flush them together. This is especially useful when you want to invalidate all cached data related to a specific entity:

// Store with tags
Cache::tags(['articles', 'homepage'])->put('featured_articles', $articles, 3600);

// Flush everything tagged 'articles'
Cache::tags(['articles'])->flush();

Note: the file and database drivers do not support tags. Use Redis or Memcached if you need them.

Lock-Based Caching

If multiple processes might try to populate the same cache key simultaneously, use a lock to prevent a thundering herd:

$result = Cache::lock('generate-report', 10)->get(function () {
    // Only one process runs this at a time
    return generateExpensiveReport();
});

When to Cache

Cache is most valuable for:

  • Database queries that return the same data across many requests (navigation menus, config values, lookup tables).
  • External API responses that do not change frequently.
  • Rendered HTML fragments that are expensive to build.

Avoid caching data that is user-specific or changes on every request — it adds complexity without a performance gain.

Tips

  • Set cache TTLs (time-to-live) conservatively at first. It is easier to shorten a TTL than to track down stale data.
  • Use a consistent key-naming convention (e.g., {entity}:{id}:{data}) to make debugging and manual cache inspection straightforward.
  • In tests, set CACHE_DRIVER=array so each test starts with a clean cache and you do not accidentally depend on cached state from a previous test.
  • Combine caching with Laravel's config:cache and route:cache in production for maximum bootstrap performance.