← Back to the section

Imagine this: every request to the home page reads the same data from the database over and over. As long as there are few users, it's tolerable. But the more requests come in, the longer each one waits. Redis solves this by keeping hot data right in RAM.

Why Redis is so fast

Redis is an in-memory key-value store. Unlike PostgreSQL or MySQL, which keep data on disk, Redis holds everything in RAM. Accessing memory is orders of magnitude faster than disk operations: microseconds instead of milliseconds.

The second reason for its speed is single-threaded command processing. Redis doesn't waste time on locks and context switches between threads: commands run sequentially, without contention. Each individual command (GET, SET, ZADD) is atomic — no partial states.

A short formula: RAM + single-threaded model = sub-1 ms latency per operation.

When to use Redis

Redis is a good fit for tasks that need fast data access or temporary storage:

Cache — the most common case. Store the result of a heavy database query in Redis for a few minutes. The next user gets an instant response, without hitting the database.

Sessions — instead of keeping state in the database or in the memory of a single process, the session lives in Redis. This lets you run several instances of the application: any of them can find the user's session.

Counters — the atomic INCR command increments a number without the risk of a data race. Handy for view counts, likes, and ratings.

Rate limiting — limiting the number of requests. We store a counter of requests over the last minute with automatic expiration (TTL), which makes it easy to implement "no more than 100 requests per minute".

Task queues — the list structure (LIST) lets you build a simple queue: one process adds tasks, another picks them up and runs them.

When Redis is not a good fit

Redis is not a replacement for your primary database — and that's important to understand from the very start.

By default, Redis keeps everything in memory. If the process crashes without persistence enabled, the data is gone. That's fine for a cache, but unacceptable for orders, invoices, or user profiles.

Don't store large volumes of data in Redis: RAM is more expensive than disk, and Redis can't run complex JOIN queries or full-text search.

Rule: Redis is an accelerator next to your primary database, not a replacement for it.

Basic commands

Before wiring up a library, it's useful to work with Redis directly through the CLI.

Start the client:

redis-cli

SET and GET — write and read

# Write a string
SET user:42:name "Ivan"

# Read
GET user:42:name
# → "Ivan"

The key is an arbitrary string. The convention is to build names with colons: entity:id:field. This makes it convenient to search and to understand the structure of your data.

EXPIRE and TTL — key lifetime

TTL (time to live) — how many seconds the key still has to live. When the time runs out, Redis deletes it automatically.

# Set a TTL of 60 seconds
EXPIRE user:42:name 60

# Check how much is left
TTL user:42:name
# → 58  (2 seconds have passed)
# → -1  (no TTL set, the key lives forever)
# → -2  (the key has already been deleted)

You can set a key and its TTL with a single command:

# SET with the EX option — expires in 300 seconds
SET session:abc123 "session data" EX 300

DEL — delete manually

DEL user:42:name
# → 1 (one key deleted)

EXISTS — check for presence

EXISTS user:42:name
# → 1 (present) or 0 (absent)

SETNX — write only if the key doesn't exist

SETNX (SET if Not eXists) — an atomic operation: the key is set only when it doesn't already exist. This is the foundation for distributed locks.

SETNX lock:order:99 "worker-1"
# → 1 (success — nobody holds the lock)
# → 0 (the key already exists — someone else grabbed it)

Connecting from Java / Spring Boot

In Spring Boot, connecting to Redis rests on three things: a dependency, configuration in application.yml, and a RedisTemplate bean or automatic caching via @Cacheable.

Dependency

// build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

Spring Boot automatically pulls in Lettuce — an asynchronous Redis client.

Connection configuration

# application.yml
spring:
  data:
    redis:
      host: localhost
      port: 6379

Writing and reading via RedisTemplate

RedisTemplate is the low-level approach: full control over keys, values, and TTL.

@Service
public class CacheService {

    private final RedisTemplate<String, String> redisTemplate;

    public CacheService(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void save(String key, String value, long ttlSeconds) {
        redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(ttlSeconds));
    }

    public String load(String key) {
        return redisTemplate.opsForValue().get(key);
    }
}

Automatic caching via @Cacheable

For caching method results, Spring offers annotations — you don't need to wire up Redis by hand.

@Service
public class ProductService {

    // The method result is stored in Redis under the key "products::<id>"
    @Cacheable(value = "products", key = "#id")
    public Product findById(Long id) {
        // called only on a cache miss
        return productRepository.findById(id).orElseThrow();
    }

    // On update — evict the cache for this key
    @CacheEvict(value = "products", key = "#product.id")
    public void update(Product product) {
        productRepository.save(product);
    }
}

For @Cacheable to know about Redis, add this to your configuration:

@Configuration
@EnableCaching
public class CacheConfig {
}

In short

  • Redis is an in-memory key-value store; it's fast thanks to RAM and single-threaded command processing.
  • It fits caching, sessions, counters, queues, and rate limiting.
  • It does not replace your primary database: without persistence, data lives only while the process is running.
  • Core commands: SET / GET / DEL / EXISTS / EXPIRE / TTL / SETNX.
  • TTL — a key's lifetime; Redis deletes it automatically once it expires.
  • In Spring Boot it connects via spring-boot-starter-data-redis (Lettuce); for caching — @Cacheable / @CacheEvict.
  • Redis data structures — strings, lists, sets, hashes, sorted sets, and when to choose which.
  • Caching patterns — cache-aside, read-through, write-through: how to build a cache correctly and when to evict it.
  • Redis and Spring Boot — a deep dive into RedisTemplate, serialization, Pub/Sub, and session management.