Card 05/ 07

GotchaDifficulty: Advanced1 min

The Default In-Memory Cache With More Than One Instance

Each instance keeps its own map, so an update on one leaves the others serving stale values.

With no cache library on the classpath, Spring Boot's cache is a ConcurrentHashMap held in the memory of the running process. On one instance of the application that is a real, working cache. With two or more instances behind a load balancer, each has its own separate map, and nothing keeps them in step.

The symptom is a value that is right on some requests and old on others. A fare updated through instance A is refreshed in A's map, while instance B keeps serving the old fare from its own map until that entry is evicted, and which one a request reaches depends on the load balancer.

The default needs nothing but @EnableCaching, which is why every local test passes: a laptop runs one instance. The failure only exists in a deployment with several, and nothing reports a conflict, because each map has no way to know the others exist.

The fix is a shared or coordinated cache provider: Redis, which every instance reads from the same place, or Caffeine together with a way to invalidate entries on every instance when a local cache is still wanted. spring-boot-starter-cache does not pick one for you; it wires up whichever provider it finds on the classpath, and falls back to the map when it finds none.