Building a High-Performance Java Cache with TTL, LRU, and Persistence
Lightweight, in-memory cache built in pure Java, featuring TTL-based expiration, LRU eviction, async loading, and optional disk persistence

Building a High-Performance Java Cache with TTL, LRU, and Persistence
Introduction
Caching is an essential technique to improve the performance of applications by reducing expensive computations and database calls. While existing caching solutions like Ehcache and Caffeine are powerful, they can be overkill for small projects. Enter MicroCache — a lightweight, in-memory cache built in pure Java, featuring TTL-based expiration, LRU eviction, async loading, and optional disk persistence.
Why Build a Custom Cache?
Most developers rely on third-party caching libraries, but sometimes, a simpler, self-contained solution is preferable. MicroCache offers:
- 🚀 Minimal dependency overhead — pure Java, no external libraries.
- ⏳ Time-To-Live (TTL) support — automatic expiration of stale items.
- ♻️ Least Recently Used (LRU) eviction — removes old entries when the cache reaches capacity.
- ⚡ Asynchronous data loading — fetch missing data in the background.
- 💾 Optional persistence — store and reload cache data across application restarts.
How It Works
MicroCache leverages Java’s ConcurrentHashMap for thread-safe operations and ScheduledExecutorService to handle TTL expiration. It supports both synchronous and asynchronous retrieval of values.
Key Features
- ✅ Thread-safe caching using ConcurrentHashMap
- ✅ TTL expiration — auto-removes old data
- ✅ LRU eviction — manages memory efficiently
- ✅ Async loading — avoids blocking operations
- ✅ Optional disk persistence — ensures data durability
- ✅ Memory monitoring — tracks resource usage
Code Walkthrough
1️⃣ Initializing MicroCache
Creating an instance of MicroCache is simple. You can specify a TTL, LRU size, and whether to enable persistence.
MicroCache<String, String> cache = new MicroCache<>(
key -> System.out.println("Expired: " + key),
key -> "Loaded async value for " + key,
100, // Max size
"cache_data.ser", // Persistence file
true // Enable persistence
);
2️⃣ Adding and Retrieving Values
cache.put("testKey", "Hello, World!", 5000); // Store value with 5s TTL
System.out.println(cache.get("testKey")); // Retrieves value
3️⃣ Handling Expiration
Thread.sleep(6000); // Wait for expiration
System.out.println(cache.get("testKey")); // Should return null
4️⃣ Performance Testing
long start = System.nanoTime();
for (int i = 0; i < 100000; i++) {
cache.put("key" + i, "value" + i, 5000);
}
long end = System.nanoTime();
System.out.println("Insertion time: " + (end - start) / 1_000_000 + " ms");
System.out.println("Memory usage: " + MicroCache.getMemoryUsage() + " MB");
Why MicroCache?
While other caching solutions exist, MicroCache is perfect for lightweight, standalone applications. It provides a great learning experience for Java developers looking to understand concurrent programming and memory management.
Final Thoughts
MicroCache is open-source! You can find the complete project on GitHub: MicroCache Repository. Feel free to explore, contribute, and suggest improvements!
MicroCache is a flexible and efficient caching solution that brings the power of TTL expiration, LRU eviction, and persistence into a simple Java-based library. Whether you’re working on a small microservice or need a lightweight caching layer, MicroCache delivers without the complexity of third-party dependencies.
Let me know what you think about MicroCache in the comments! 🚀
메타데이터
- post_id
- 3dbd5f0dcf1e
- slug
- building-a-high-performance-java-cache-with-ttl-lru-and-persistence-3dbd5f0dcf1e
- url
- https://medium.com/@dev.jefster/building-a-high-performance-java-cache-with-ttl-lru-and-persistence-3dbd5f0dcf1e
- canonical_url
- https://medium.com/@dev.jefster/building-a-high-performance-java-cache-with-ttl-lru-and-persistence-3dbd5f0dcf1e
- author_url
- https://medium.com/@dev.jefster
- status
- ok
- fetched_at
- 2026-06-17 08:20:12