DEV Community

Said Olano
Said Olano

Posted on

EhCache: A Practical Guide to Embedded Caching in Java (2026-08-21 22:11)

EhCache: Embedded Caching Solution

Caching is one of the most effective ways to improve application performance. By keeping frequently accessed data close to your application logic, you avoid expensive round-trips to databases or remote services. EhCache is a mature, widely-used, open-source caching library for Java that makes embedded caching straightforward.

In this post, we'll explore what EhCache offers, how to configure it, and best practices for using it in production.

What Is EhCache?

EhCache is an in-process (embedded) caching library that runs within the same JVM as your application. Unlike distributed caches such as Redis or Memcached, EhCache stores data locally, which means near-instant access times without network overhead.

Key characteristics:

  • Embedded and lightweight — no separate server process required.
  • Tiered storage — supports heap, off-heap, and disk-based storage.
  • JSR-107 (JCache) compliant — integrates with the standard Java caching API.
  • Spring integration — works seamlessly with Spring's caching abstraction.

Adding EhCache to Your Project

For EhCache 3.x with Maven, add the following dependency:

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.10.8</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

If you want JCache (JSR-107) support:

<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.1.1</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Programmatic Configuration

EhCache 3 offers a clean, type-safe builder API for configuring caches in code:

import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.*;
import org.ehcache.config.units.*;

public class CacheExample {
    public static void main(String[] args) {
        CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
            .withCache("productCache",
                CacheConfigurationBuilder.newCacheConfigurationBuilder(
                    Long.class, String.class,
                    ResourcePoolsBuilder.newResourcePoolsBuilder()
                        .heap(1000, EntryUnit.ENTRIES)
                        .offheap(10, MemoryUnit.MB)))
            .build(true);

        Cache<Long, String> productCache =
            cacheManager.getCache("productCache", Long.class, String.class);

        productCache.put(1L, "Wireless Mouse");
        String value = productCache.get(1L);
        System.out.println("Cached value: " + value);

        cacheManager.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

Understanding Tiered Storage

One of EhCache's strengths is its tiered storage model. You can combine multiple tiers, and EhCache automatically moves data between them based on usage.

Tier Location Speed Capacity
Heap JVM heap Fastest Limited by heap size
Off-heap Native memory Fast Larger, no GC pressure
Disk Local disk Slower Very large, persistent

A common configuration uses heap for hot data and off-heap to hold a larger working set without increasing garbage collection pressure.

Setting Expiration Policies

Stale data can cause bugs, so expiration is essential. EhCache supports time-to-live (TTL) and time-to-idle (TTI) policies:

CacheConfigurationBuilder.newCacheConfigurationBuilder(
        Long.class, String.class,
        ResourcePoolsBuilder.heap(1000))
    .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(
        Duration.ofMinutes(10)))
    .build();
Enter fullscreen mode Exit fullscreen mode
  • Time-to-live — entry expires a fixed time after creation.
  • Time-to-idle — entry expires after a period of no access.

XML Configuration

If you prefer externalized configuration, EhCache supports XML. Create an ehcache.xml file:

<config xmlns='http://www.ehcache.org/v3'>
    <cache alias="productCache">
        <key-type>java.lang.Long</key-type>
        <value-type>java.lang.String</value-type>
        <expiry>
            <ttl unit="minutes">10</ttl>
        </expiry>
        <resources>
            <heap unit="entries">1000</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache>
</config>
Enter fullscreen mode Exit fullscreen mode

Load it like this:

URL myUrl = getClass().getResource("/ehcache.xml");
CacheManager cacheManager =
    CacheManagerBuilder.newCacheManager(new XmlConfiguration(myUrl));
cacheManager.init();
Enter fullscreen mode Exit fullscreen mode

Integrating with Spring

EhCache works well with Spring's @Cacheable abstraction through JCache. Enable caching and let annotations handle the rest:

@Configuration
@EnableCaching
public class CacheConfig {
    // JCacheManagerFactoryBean or JCacheCacheManager wiring here
}

@Service
public class ProductService {

    @Cacheable(value = "productCache", key = "#id")
    public Product findProduct(Long id) {
        // Expensive database lookup — cached after first call
        return productRepository.findById(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices

  • Size your caches deliberately. Overly large heap caches increase GC pauses. Prefer off-heap for large datasets.
  • Always set expiration.

Top comments (0)