Cache-Aside
The application manages the cache itself
With Cache-Aside, the cache sits next to the primary store, but the application decides when to read from it and when to access the data source.
The read path usually works like this: first look for the value in the cache. On a hit, return it immediately. On a miss, read the primary source, put the result into the cache, and only then respond.
Product getProduct(long id) {
String key = "product:" + id;
Product product = cache.get(key);
if (product != null) {
return product;
}
product = repository.findById(id);
cache.put(key, product);
return product;
}
Why this pattern is popular
Cache-Aside does not require the cache to know how to work with the database by itself. The application controls keys, value format, and when entries are populated, so the pattern can be added around an existing read path relatively easily.
Only data that is actually requested enters the cache. If nobody reads an object, no cache memory is spent on it.
A miss is still expensive
The first request for an absent key takes the full path to the primary source, so its latency does not become lower. The following reads become faster after the cache is populated.
If many requests miss the same popular key at the same time, they can reach the primary store almost simultaneously. This matters for data that suddenly becomes popular.
Data changes need a separate decision
Cache-Aside mainly describes the read path. After data changes, the application must make sure the old copy does not remain in the cache forever. We will examine concrete ways to update or remove stale values separately in the cache invalidation topic.