DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Versioned Caching: A Practical Pattern for High-Performance Lookup Data
  • Every Cache Miss Is a Tiny Tax on Your Performance
  • The Bill You Didn't See Coming
  • Why Angular Performance Problems Are Often Backend Problems

Trending

  • DZone's Article Submission Guidelines
  • How to Submit a Post to DZone
  • Implementing Secure API Gateways for Microservices Architecture
  • Implementing Observability in Distributed Systems Using OpenTelemetry
  1. DZone
  2. Data Engineering
  3. Data
  4. Fine-Tuning of Spring Cache

Fine-Tuning of Spring Cache

Caching is a fundamental concept for making web applications faster and more scalable. In the following, I explain how to configure and optimize Spring caching.

By 
Constantin Kwiatkowski user avatar
Constantin Kwiatkowski
·
Apr. 17, 26 · Analysis
Likes (1)
Comment
Save
Tweet
Share
2.4K Views

Join the DZone community and get the full member experience.

Join For Free

Caching is one of the most effective techniques for improving the performance of modern Spring applications. Especially in microservice architectures or high-traffic APIs, a well-configured cache can significantly reduce database load and greatly improve response times. By storing frequently accessed data in memory, applications can avoid repeated expensive operations such as database queries or external API calls. This article provides a compact yet comprehensive overview of Spring’s caching capabilities. 

For example, without caching, each request follows this process:

Plain Text
 
Client → Web Server → Application → Database


When 10,000 users request the same data, without caching, this results in 10,000 database queries, high latency, and significant server load. With caching:

Plain Text
 
Client → Web Server → Application → Cache → Database


The first request hits the database, and the result is stored in the cache. Subsequent requests are served directly from the cache. This reduces database load, speeds up responses, and enhances scalability.

Caching can be implemented at multiple levels within a web application:

  1. Browser Cache
    The browser stores static files such as images, CSS, and JavaScript. This prevents these files from being downloaded on every request, reducing load time and network usage.
  2. CDN Cache
    A Content Delivery Network (CDN) caches content across multiple servers geographically. Examples include Cloudflare and Akamai. This reduces latency for users worldwide and improves page load speed.
  3. Server / Application Cache
    Data is stored within the application or server to speed up access to frequently requested information. Typical examples include database query results, API responses, or computational results. Common technologies for this level include Redis, Ehcache, Caffeine, and Apache Ignite.

Spring Cache

The caching module in the Spring Framework implements precisely this application-level cache. Spring provides an abstraction layer that allows developers to define caching very easily using annotations. Spring handles cache access, storage, and invalidation, so the developer only needs to specify which methods should be cached. 

Architecture

Typical architecture:

Plain Text
 
Client
   ↓
Controller
   ↓
Service  (@Cacheable)
   ↓
Cache (Redis / Caffeine / Ignite)
   ↓
Database
-------

Controller
   │
   ▼
Spring Proxy
   │
   ▼
CacheInterceptor
   │
   ▼
CacheManager → Cache Lookup
   │
   ├── Cache Hit → Return Value
   │
   └── Cache Miss
          │
          ▼
     Service Method
          │
          ▼
     Cache Put
          │
          ▼
     Return Value


Spring sits between the service and the underlying cache system, providing a caching API that enables significant performance improvements. Spring defines the caching logic, while a cache provider handles data storage. The Spring caching abstraction offers several benefits: simple implementation via annotations, pluggable cache providers, reduced database load, and improved performance. Supported providers include Redis, Ehcache, Caffeine, and Apache Ignite.

Spring caching is typically built on proxy-based Aspect-Oriented Programming (AOP). A proxy object is placed between the caller and the service method. The simplified flow looks like this:

Plain Text
 
Controller → Proxy → Cache Check → Service Method


If a cache hit occurs, the actual service method is not executed; instead, the proxy returns the cached value immediately. 

Remarks: Spring supports two types of proxies: JDK Dynamic Proxies used for interfaces and CGLIB Proxies used for classes without interfaces. However, proxy-based AOP has some limitations: Internal method calls bypass the proxy, private methods cannot be intercepted, and Final methods cannot be proxied. For more complex scenarios, AspectJ weaving can be used as an alternative, which allows direct bytecode modification and interception without relying on proxies.

Tuning of Spring Cache

The fine-tuning of the Spring cache system is primarily done through the choice of cache provider. The following table provides an overview of different cache providers, their typical use cases, and the associated advantages and disadvantages.   

CACHE PROVIDER TYPE USE CASE ADVANTAGES DISADVANTAGES
ConcurrentMapCache Local Small applications / testing Simple, no external dependency No TTL, no eviction
Caffeine Local High-performance APIs Very fast, modern eviction algorithms, async loading Local only
EhCache Local + Persistence Applications with long-lived cache data Disk persistence possible More complex configuration
Redis Distributed Web apps / microservices Very fast, cluster-capable Network latency
Hazelcast Distributed Cluster applications In-memory grid, automatic replication Higher resource consumption
Infinispan Distributed Enterprise systems Scalable, supports transactions Complex operation


The next table provides an overview of tuning parameters and their effects on the cache system, which can be used in conjunction with a cache provider.

PARAMETER MEANING TYPICAL VALUE / RECOMMENDATION EFFECT
maximumSize / maxEntries Maximum number of cache entries 500–5,000 local, 10k+ distributed Prevents memory overflow
expireAfterWrite / TTL Time-to-live after write 5–60 minutes Prevents stale data
expireAfterAccess / TTI Time-to-idle since last access 5–60 minutes Removes rarely used data
Eviction Policy Strategy for removing entries LRU standard, LFU for hot keys Optimizes memory usage
refreshAfterWrite Background refresh Optional Prevents cache misses
initialCapacity Initial size of the cache Set high for large caches Less rehashing / locking
backupCount Replication in cluster 1–2 Higher fault tolerance
overflowToDisk Persistence outside of heap For large data Reduces heap usage


Based on the insights gained so far, various strategies can now be applied to achieve improved caching performance. The following table explains some of these strategies.

Technique Description Impact
sync=true Prevents cache stampede Avoids DB storms
Local Cache before Redis Multi-level caching 10–50× faster responses
Increase initialCapacity Reduces resizing and rehashing Less lock contention
Key optimization Use simple keys 10–20% performance improvement
Negative caching Cache null results Up to 80% DB load reduction
Async cache loading Non-blocking data retrieval Better scalability
Cache warmup Preload cache at startup Stable latency after deployment


Let's break down some of these concepts and analyze a few examples.

Many caches start with a small initial capacity, which causes internal data structures to resize frequently. An example using Caffeine:

Plain Text
 
Caffeine.newBuilder().initialCapacity(100000).maximumSize(1000000).build();


A larger initial capacity reduces rehash operations and improves scalability.

Another important concept is negative caching, where even negative results are stored in the cache. For example, if a user ID does not exist and every request queries the database again, this can create unnecessary load. By caching null results, this effect can be avoided.

Modern caching libraries like Caffeine also support asynchronous data loading, allowing non-blocking computation and improved parallelism for high-traffic applications.

Plain Text
 
buildAsync(key -> loadUser(key));


This reduces thread blocking, which is especially beneficial in highly parallelized systems.  

After a deployment, many caches are initially empty. This can cause performance spikes if a large number of requests suddenly hit the database. A simple solution is to perform a cache warm-up when the application starts:

Plain Text
 
@PostConstruct public void warmCache() {    service.getUser(1);    service.getUser(2); }


This pre-populates the cache with frequently used data at startup. 

In addition to the performance strategies mentioned so far, the choice of proxy type for the caching system can also impact performance (proxy-based AOP). In Spring, there are two proxy types: JDK Dynamic Proxies and CGLIB. The following table provides an overview of the differences between them.

PROXY TYPE IMPLEMENTATION PERFORMANCE TYPICAL USE CASE
JDK Dynamic Proxy Java Reflection + Interface Proxy Minimally slower on method calls Services with interfaces
CGLIB Proxy Bytecode-generated subclass Minimally faster on calls Classes without interfaces


CGLIB generates a subclass of your class and invokes methods directly via bytecode. Internal example:

Plain Text
 
UserService$$SpringCGLIBProxy extends UserService


Method Call:

Plain Text
 
proxy.getUser()
   ↓
interceptor
   ↓
super.getUser()


No reflection is needed. JDK proxies work via an InvocationHandler. Internally:

Plain Text
 
Proxy.invoke()
   ↓
InvocationHandler
   ↓
Method.invoke()


This uses reflection, which has historically been slower. The following table shows some numerical values illustrating how the choice of proxy type affects overall performance.

Operation TIME
Regular Call ~5 ns
CGLIB Proxy Call ~20–40 ns
JDK Proxy Call ~40–80 ns


When should each proxy type be used? The following table provides an overview.

Situation Advise
Microservices CGLIB
Spring Boot Standard CGLIB
Interface-heavy Architecture JDK Proxy
Performance It doesn't matter


Conclusion

Spring Cache is a powerful mechanism for improving application performance. Caching frequently accessed data significantly reduces the number of expensive operations, such as database queries or external API calls. As a result, applications can achieve lower latency, reduced backend load, and better scalability under high traffic. However, while Spring provides a variety of configuration and tuning options, not all of them have the same impact on performance. 

A good example of marginal impact is the selection of the proxy type used by Spring’s AOP infrastructure. Whether the framework uses JDK Dynamic Proxies or CGLIB proxies typically results in only negligible performance differences, since the overhead of proxy invocation is extremely small compared to the cost of database queries, network calls, or complex business logic. Therefore, performance optimization in Spring Cache should focus primarily on architectural and data-access related aspects rather than low-level framework details.

Cache (computing) Data (computing) Performance

Opinions expressed by DZone contributors are their own.

Related

  • Versioned Caching: A Practical Pattern for High-Performance Lookup Data
  • Every Cache Miss Is a Tiny Tax on Your Performance
  • The Bill You Didn't See Coming
  • Why Angular Performance Problems Are Often Backend Problems

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook