Caching Strategies for Web Applications

A breakdown of caching patterns and when to apply each one.

Key Insights

  • Cache at the highest level possible — HTTP cache beats application cache beats query cache in both simplicity and effectiveness
  • Set TTLs on everything; unbounded caches are memory leaks waiting to happen
  • Monitor cache hit rates — below 80% means your caching strategy needs rethinking

Caching is the most effective performance optimization available to web developers, but it introduces complexity. Understanding the trade-offs helps you cache effectively.

Cache-Aside (Lazy Loading)

The application checks the cache first, falling back to the database on a miss:

func GetUser(ctx context.Context, id string) (*User, error) {
    cached, err := cache.Get(ctx, "user:"+id)
    if err == nil {
        return cached.(*User), nil
    }

    user, err := db.GetUser(ctx, id)
    if err != nil {
        return nil, err
    }

    cache.Set(ctx, "user:"+id, user, 5*time.Minute)
    return user, nil
}

Best for: Read-heavy data that’s expensive to compute.

Write-Through

Every write updates both the cache and the database:

Best for: Data that’s read immediately after writing.

Write-Behind

Writes go to the cache immediately and are asynchronously flushed to the database:

Best for: High write throughput where eventual consistency is acceptable.

Cache Invalidation

The hardest problem in caching. Three approaches:

  1. TTL-based: Set an expiration and accept stale data within that window.
  2. Event-based: Invalidate on write operations.
  3. Version-based: Include a version key; increment on changes.

Rules of Thumb

  • Cache at the highest level possible (HTTP cache > application cache > query cache)
  • Set TTLs on everything — unbounded caches are memory leaks
  • Monitor hit rates; below 80% suggests your caching strategy needs work
  • Never cache user-specific data without proper key isolation

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.