← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Caching Strategies

performance PHP 7.0+ Intermediate

Also Known As

cache-aside write-through write-behind read-through lazy loading cache cache invalidation

TL;DR

Patterns for when and how to store and invalidate cached data — cache-aside, write-through, write-behind, and read-through each make different trade-offs between consistency, complexity, and performance.

Explanation

The four core caching strategies: Cache-aside (lazy loading) — the application checks the cache first; on a miss, loads from the database, stores in cache, returns the result. The application controls all cache interactions. Write-through — writes go to both the cache and the database synchronously; reads always hit cache. Strong consistency, higher write latency. Write-behind (write-back) — writes go to cache immediately and to the database asynchronously; fast writes, risk of data loss if cache fails before persisting. Read-through — the cache itself loads from the database on a miss; the application only ever talks to the cache layer. In PHP, cache-aside with Redis or Memcached is the most common pattern. Cache invalidation strategies: TTL-based (expire after N seconds), event-based (invalidate on write), and pattern-based (purge all keys matching a prefix). The hardest problem in caching is stale data — knowing when cached data no longer reflects the source of truth.

Common Misconception

Caching always improves performance. Poorly implemented caching introduces bugs worse than the performance problem it was meant to solve. Caching user-specific data without proper key namespacing leaks data between users. Caching without a TTL produces stale data that never refreshes. Caching inside a transaction produces incorrect data if the transaction rolls back. Measure first — caching premature to a performance diagnosis adds complexity without solving the actual bottleneck.

Why It Matters

Caching is the most impactful single change for read-heavy PHP applications. A product page querying 12 database tables on every request scales to hundreds of requests per second with a 60-second cache; without caching it falls over at dozens. The cache-aside pattern with Redis is implementable in under 30 lines of PHP and immediately reduces database load by the cache hit ratio. Proper TTL and invalidation strategy choice prevents the stale data bugs that make developers distrust their cache and flush it manually.

Common Mistakes

  • Not namespacing cache keys by user or tenant — global keys like 'user_profile' serve the same cached data to all users.
  • Caching inside database transactions — if the transaction rolls back, the cached data is inconsistent with the database.
  • Using a single global TTL for all cache entries — frequently updated data needs short TTLs; rarely changing data can cache for hours.
  • Cache stampede on TTL expiry — many concurrent requests all miss and hit the database simultaneously; use probabilistic early expiry or a mutex lock on cache population.

Avoid When

  • Cache-aside on data that is written frequently — the cache is invalidated constantly and hit rate stays near zero.
  • Write-through on data that is rarely read — you pay the write overhead for cache entries that are never served.
  • Caching user-specific data in a shared cache without namespacing keys — data bleeds between users.
  • Caching without a TTL — stale entries accumulate and are never evicted.

When To Use

  • Cache-aside for read-heavy data that changes infrequently and tolerable staleness exists.
  • Write-through for data that is written and then immediately read, where cache miss after write is unacceptable.
  • Read-through when the application should never query the DB directly — the cache layer owns all reads.
  • Write-behind (write-back) for high-write workloads where batching DB writes improves throughput.

Code Examples

✗ Vulnerable
// No caching — hits database on every request
class ProductController {
    public function show(int $id): array {
        // Expensive query on every page load
        return $this->db->query(
            'SELECT p.*, c.name as cat, AVG(r.score) as rating
             FROM products p
             JOIN categories c ON p.cat_id = c.id
             LEFT JOIN reviews r ON r.product_id = p.id
             WHERE p.id = ?
             GROUP BY p.id', [$id]
        )->fetch();
    }
}
✓ Fixed
// Cache-aside with Redis — database hit only on miss
class ProductController {
    public function show(int $id): array {
        $key    = 'product:' . $id;
        $cached = $this->redis->get($key);
        if ($cached) return json_decode($cached, true);

        $product = $this->db->query('...expensive query...', [$id])->fetch();
        $this->redis->setex($key, 3600, json_encode($product)); // 1hr TTL
        return $product;
    }

    public function update(int $id, array $data): void {
        $this->db->query('UPDATE products SET ...', $data);
        $this->redis->del('product:' . $id); // invalidate on write
    }
}

Added 23 Mar 2026
Edited 5 Apr 2026
Views 45
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 2 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 14 Perplexity 11 Google 6 Meta AI 2 Ahrefs 2 SEMrush 2 ChatGPT 1
crawler 35 crawler_json 3
DEV INTEL Tools & Severity
🔵 Info ⚙ Fix effort: Medium
⚡ Quick Fix
Implement cache-aside: $data = $cache->get($key) ?? tap($db->find($id), fn($v) => $cache->set($key, $v, 3600)) — check cache, populate on miss, set TTL
📦 Applies To
PHP 7.0+ web cli

✓ schema.org compliant