← All articles
Backend1 min read

Caching Strategies: Cache-Aside, Write-Through, and Write-Behind

Caching is easy to add and easy to get wrong. Understanding the three core patterns helps you pick the right consistency trade-off.

S

Swapnika Voora

Author

Adding a cache is a one-line annotation; keeping it correct is the hard part. Three patterns cover most needs, and each trades freshness against latency differently.

Cache-aside (lazy loading)

The application checks the cache first, loads from the database on a miss, and populates the cache. This is the most common pattern and what Spring's @Cacheable implements.

CacheAside.java
public Product find(Long id) {
    Product cached = cache.get(id);
    if (cached != null) return cached;
 
    Product loaded = repository.findById(id).orElseThrow();
    cache.put(id, loaded);
    return loaded;
}

Write-through

Writes go to the cache and the database together, so the cache is never stale — at the cost of slower writes.

WriteThrough.java
public Product save(Product product) {
    Product saved = repository.save(product);
    cache.put(saved.getId(), saved);   // cache updated synchronously
    return saved;
}

Write-behind

Writes hit the cache immediately and flush to the database asynchronously. This is fast but risks data loss if the process dies before the flush.

WriteBehind.java
public void save(Product product) {
    cache.put(product.getId(), product);
    writeQueue.enqueue(product);   // persisted later, in the background
}

Takeaways

  • Cache-aside is the safe default and matches @Cacheable.
  • Write-through keeps the cache fresh but slows writes.
  • Write-behind is fastest but sacrifices durability — use it carefully.

Whichever you pick, always set a TTL. Expiry is your backstop for the cache invalidation bugs you haven't found yet.

#java#caching#architecture#performance

More in Backend