Caching in Kotlin: Redis, Caffeine and Other Solutions

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Caching in Kotlin: Redis, Caffeine and Alternatives



Caching is one of the key tools for improving application performance. In Kotlin, thanks to compatibility with Java and the rich JVM ecosystem, many solutions are available: from lightweight in-memory cache to distributed systems based on Redis. In this article, we will review popular libraries, their setup, and usage examples.



Why is caching needed?

The main goals of caching:

  • Reducing response time (latency) by storing frequently requested data in fast memory.
  • Reducing load on databases and external APIs.
  • Saving computational resources on repeated requests.


Kotlin allows using both native Java libraries and specialized Kotlin wrappers.



1. Redis via Lettuce or Redisson

Redis is the most popular in-memory data store for distributed caching. In Kotlin, it is connected via Lettuce (reactive) or Redisson (synchronous/asynchronous) clients.



Example: caching with Lettuce

// build.gradle.ktsimplementation("io.lettuce:lettuce-core:6.3.1.RELEASE")

// CacheService.ktimport io.lettuce.core.RedisClientimport io.lettuce.core.api.sync.RedisCommands

class RedisCache(private val host: String = "localhost", private val port: Int = 6379) { private val client: RedisClient = RedisClient.create("redis://$host:$port") private val connection = client.connect() private val sync: RedisCommands<String, String> = connection.sync()

fun get(key: String): String? = sync.get(key) fun set(key: String, value: String, ttlSeconds: Long = 60) { sync.setex(key, ttlSeconds, value) } fun delete(key: String) = sync.del(key) fun close() { connection.close() client.shutdown() }}

// Usagefun main() { val cache = RedisCache() cache.set("user:123", """{"name":"Alice","role":"admin"}""", 120) val data = cache.get("user:123") println(data) // {"name":"Alice","role":"admin"} cache.close()}


Redisson — a higher-level API

implementation("org.redisson:redisson:3.27.2")

val config = Config().apply { useSingleServer().setAddress("redis://127.0.0.1:6379")}val redisson = Redisson.create(config)val map = redisson.getMap<String, String>("userCache")map["user:456"] = """{"name":"Bob"}"""val bob = map["user:456"]redisson.shutdown()


2. Caffeine — fast in-memory cache

Caffeine is a modern replacement for Guava Cache. It is optimized for high loads and supports automatic eviction of stale entries.



implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")

import com.github.benmanes.caffeine.cache.Cacheimport com.github.benmanes.caffeine.cache.Caffeineimport java.util.concurrent.TimeUnit

val cache: Cache<String, String> = Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(10_000) .recordStats() .build()

// Write and readcache.put("key1", "value1")val value = cache.getIfPresent("key1")println(value) // value1

// Statisticsval stats = cache.stats()println("Hit rate: ${stats.hitRate()}")


3. Hazelcast — distributed cache with clustering

Hazelcast is suitable for microservice architectures: the cache is automatically synchronized between nodes.



implementation("com.hazelcast:hazelcast:5.3.6")

import com.hazelcast.core.Hazelcastimport com.hazelcast.map.IMap

val instance = Hazelcast.newHazelcastInstance()val map: IMap<String, String> = instance.getMap("session-cache")map.put("session:token123", "userId=42", 30, TimeUnit.MINUTES)val userId = map.get("session:token123")instance.shutdown()


4. Spring C

Recommendations