Caching in Kotlin: Redis, Memcached, and Built-in Solutions — from A to Z
Caching is one of the key tools for improving application performance. In the Kotlin ecosystem, which runs on top of JVM and Android, developers have access to many solutions: from distributed systems (Redis, Memcached) to built-in local caches (Caffeine, Guava Cache, Ehcache). In this article, we will break down how to integrate each of them into a Kotlin project, provide code examples, and give recommendations for selection.
1. Built-in Caching on JVM: Caffeine and Guava Cache
For local caching in Kotlin, Caffeine is the best choice — a high-performance library written in Java and fully compatible with Kotlin. It supports automatic eviction by time, by size, and based on weights. An alternative is Guava Cache from Google, but Caffeine is faster (often 2-3 times).
Example: Caffeine + Kotlin
Add the dependency in build.gradle.kts:
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")Create a cache for 1000 elements with a TTL of 10 minutes:
import com.github.benmanes.caffeine.cache.Caffeineimport java.util.concurrent.TimeUnit
val cache = Caffeine.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .build<String, String>()
// Usagecache.put("user:42", "{\\"name\\":\\"Alice\\"}")val user = cache.getIfPresent("user:42")println(user) // {"name":"Alice"}Example: Guava Cache + Kotlin
implementation("com.google.guava:guava:33.0.0-jre")import com.google.common.cache.CacheBuilderimport java.util.concurrent.TimeUnit
val guavaCache = CacheBuilder.newBuilder() .maximumSize(500) .expireAfterWrite(5, TimeUnit.MINUTES) .build<String, String>()
guavaCache.put("session:abc", "active")println(guavaCache.getIfPresent("session:abc")) // activeWhen to use: for storing temporary data of a single application instance (e.g., results of complex calculations, tokens, configurations). Not suitable for microservices with multiple instances — data is not synchronized.
2. Redis — Distributed Caching for Microservices
Redis is an in-memory key-value store used as a distributed cache, message broker, and database. For Kotlin, the best client is Lettuce (asynchronous, reactive, thread-safe).
Installation and Connection
implementation("io.lettuce:lettuce-core:6.3.2.RELEASE")Example: Connection and Basic Operations
import io.lettuce.core.RedisClientimport io.lettuce.core.api.sync.RedisCommands
val client = RedisClient.create("redis://localhost:6379")val connection = client.connect()val commands: RedisCommands<String, String> = connection.sync()
// Set a key with TTL of 60 secondscommands.setex("user:123", 60, "{\\"name\\":\\"Bob\\"}")
// Readval data = commands.get("user:123")println(data) // {"name":"Bob"}
connection.close()client.shutdown()Example: Reactive Client (Kotlin Coroutines)
import io.lettuce.core.RedisClientimport io.lettuce.core.api.reactive.RedisReactiveCommandsimport kotlinx.coroutines.reactive.awaitFirstOrNull
suspend fun getFromRedis(key: String): String? { val client = RedisClient.create("redis://localhost:6379") val connection = client.connect() val reactive: RedisReactiveCommands<String, String> = connection.reactive()
val result = reactive.get(key).awaitFirstOrNull() connection.close() client.shutdown() return result}When to use: distributed systems, microservices, shared sessions, rate limiting, pu