Caching in Kotlin: Redis 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 and Other Solutions



Caching is one of the key mechanisms for optimizing performance in modern applications. In the Kotlin ecosystem, thanks to full compatibility with Java and the rich JVM library base, all major tools for working with cache are available. In this article, we will look at how to organize caching in Kotlin using Redis, Caffeine, and Ehcache, and also analyze when to choose which tool.



Why is caching needed?

Cache allows you to reduce application response time by storing frequently requested data in fast-access memory. This is especially relevant for:

  • high-load REST APIs;
  • working with external APIs and databases;
  • resource-intensive computations;
  • user session data.


Basic Caching Strategies

Before choosing a library, it is important to understand the basic strategies:

  • Cache-Aside — the application manages the cache itself: it first checks the cache, on a miss loads data from the database and puts it into the cache.
  • Read-Through — the cache automatically loads data from the source on a miss.
  • Write-Through / Write-Behind — writing data simultaneously (or asynchronously) to the cache and the main storage.


1. Redis from Kotlin

Redis is an in-memory key-value store that is often used as a distributed cache. To work with Redis in Kotlin, the Lettuce client (asynchronous, reactive) or Jedis (synchronous) is used.



Adding Lettuce

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


Example of working with Redis via Lettuce (Kotlin)

import io.lettuce.core.RedisClientimport io.lettuce.core.api.coroutines

suspend fun main() { val client = RedisClient.create("redis://localhost:6379") val connection = client.connect() val commands = connection.coroutines() // coroutine API

// Write commands.setex("user:123:profile", 3600, "{\\"name\\":\\"Alice\\"}") // Read val cached = commands.get("user:123:profile") println("From cache: $cached") connection.close() client.shutdown()}


When to use Redis?

  • A distributed cache between multiple application instances is needed.
  • High fault tolerance and replication are required.
  • Data must be available after application restart (Redis persistence).
  • Support for complex structures (lists, sets, queues) is necessary.


2. Caffeine — High-Performance Local Cache

Caffeine is a library for in-memory caching on the JVM, written in Java. It is often used in conjunction with Spring Boot, but works great in pure Kotlin as well. Caffeine provides near-zero latency on reads.



Adding Caffeine

// build.gradle.ktsimplementation("com.github.ben-manes.caffeine:caffeine:3.1.8")


Example of using Caffeine in Kotlin

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

data class User(val id: Int, val name: String)

fun createCache(): Caffeine<Int, User>.() -> Unit = { maximumSize(10_000) expireAfterWrite(10, TimeUnit.MINUTES) recordStats()}

val userCache = Caffeine.newBuilder() .maximumSize(10_000) .expireAfterWrite(10, TimeUnit.MINUTES) .build<Int, User>()

fun getUserFromCache(id: Int): User? { return userCache.getIfPresent(id)}

fun putUser(id: Int, user: User) { userCache.put(id, user)}

// Example with automatic loading (LoadingCache)val loadingCache = Caffeine.newBuilder() .maximumSize(5_000) .build<Int, User>

Recommendations