Sign in
← Data
11 min · easy · Lesson 4 of 5

Redis: cache and shared state

What Redis is, why you cache in memory, how to store sessions, and why TTL and invalidation matter.

Why another storage system

Postgres stores data reliably, but reaching it costs time: a query, disk, network. If the same data gets read a thousand times a second, hitting the database every time is wasteful. Redis is an in-memory key-value store. Reading from memory is orders of magnitude faster than from the database, which is why Redis sits in front of Postgres as a cache.

A second use case, from the 12-factor lesson: stateless applications move shared state (sessions) into external storage, and Redis is a good fit for that.

Redis keeps data in memory. It can save snapshots to disk (RDB) and a command log (AOF), but when it's used as a cache, those are often turned off. So the rule is simple: the source of truth stays in Postgres, and Redis holds whatever can be lost and rebuilt.

Basic operations

Redis works by keys. Put, read, delete:

SET user:42:name "Ivan"
GET user:42:name        -- "Ivan"
DEL user:42:name
EXISTS user:42:name      -- 0 or 1

A colon in a key name means nothing to Redis. It's a convention so keys read like a path: user:42:name, cache:product:15.

Commands can be typed in redis-cli, the command-line client. In interactive mode it prints the type of the reply: "Ivan" for a string, (integer) 1 for a number, (nil) for an empty reply.

Besides strings there are structures: lists, sets, hashes, counters. A counter, for instance, increments atomically with one command, which is handy for limits and metrics:

INCR page:views        -- atomically +1, returns the new value

If the key doesn't exist, INCR treats it as zero and returns 1. If the key holds something that isn't a number, you'll get the error ERR value is not an integer or out of range.

A hash stores a set of fields under one key. That's a convenient shape for a session: user, role, login time.

HSET session:demo user_id 7 role admin    -- create or add fields
HGETALL session:demo                       -- all fields and values
TYPE session:demo                          -- hash

TTL: data with an expiration

A key can be given a time to live (TTL). When it expires, Redis deletes the key on its own. That's the basis of a cache: you put a query result in for five minutes, and after that it refreshes itself.

SET weather:moscow "{...}" EX 300    -- lives for 300 seconds
TTL weather:moscow                   -- how much is left

For a key that already exists, EXPIRE key seconds sets the TTL. That's how it's done with a hash: HSET has no parameter of its own for a time to live, so EXPIRE follows it.

TTL doesn't only reply with seconds. -1 means the key exists but lives forever. -2 means the key doesn't exist: it expired, or it was never created.

Without a TTL, a cache grows and fills up memory. That's why cache keys almost always get a TTL.

When memory runs out

How much memory Redis can use is set by the maxmemory parameter. By default it's 0, meaning no limit, and Redis grows until it hits the machine's memory or the container's limit. In production, the limit is set explicitly.

What to do when the limit is hit is decided by maxmemory-policy. By default it's noeviction: Redis doesn't evict anything, reads keep working, and writes are rejected with an error:

OOM command not allowed when used memory > 'maxmemory'.

Other policies evict keys on their own. allkeys-lru evicts the least recently used keys from all keys, volatile-lru only from keys that have a TTL. If the same Redis holds sessions without a TTL, an allkeys-* policy can evict those too and log users out.

You can see the current values like this:

CONFIG GET maxmemory
INFO memory                -- the used_memory line: how much is used right now

Cache and invalidation

A typical cache pattern is called cache-aside:

  1. the application asks Redis.
  2. the value exists (cache hit) → return it.
  3. it doesn't (cache miss) → go to Postgres, put the result in Redis with a TTL, return it.
key found · cache hit key missing · cache miss read Redis: key exists? return value Postgres SET key · TTL return UPDATE DEL key or do nothing and wait until the key's TTL runs out
A miss goes to the database and fills the cache itself. A write to the database leaves a stale value in Redis.

The hardest part of caching is invalidation: the data changed in the database, but the cache still holds the old value. There are two approaches. Rely on the TTL (the old value goes stale on its own after N seconds, fine for non-critical data), or delete the key on change (DEL after UPDATE, when you need freshness). The choice depends on how much freshness matters compared to simplicity.

Redis, Valkey and licenses

There's one more reason why the word Valkey shows up more and more often in job postings and cloud consoles.

In March 2024, the company Redis announced that starting with version 7.4, Redis ships under a pair of licenses, RSALv2 / SSPLv1. Both restrict anyone selling Redis as a service, and neither counts as open source (OSI). Cloud providers and some contributors responded by forking the last open version, 7.2.4. They named the fork Valkey and handed it to the Linux Foundation. AWS and Google Cloud launched their managed services on top of it, so a "Redis-compatible cache" in the cloud today often turns out to be Valkey.

In May 2025, Redis 8 added the open AGPLv3 license alongside those, but by then Valkey had already taken hold.

For you the difference is purely nominal right now: the same commands, the same protocol, the same client libraries. Everything from this lesson works in both. It's worth knowing just so you're not surprised by the name in a cloud console.

Common mistakes

What to remember

Redis stores data in memory by keys and reads orders of magnitude faster than a database, which is why it's used as a cache in front of Postgres and as session storage for stateless applications.

Cache keys get a TTL, otherwise memory fills up. The cache-aside pattern: a miss goes to the database and puts the result in Redis with a TTL.

The hardest part is invalidating stale data: you rely either on the TTL or on deleting the key on change, depending on the freshness requirements.

Valkey is a fork of Redis under the Linux Foundation, created after the license change in 2024. Commands and protocol are compatible.

What you'll need for the tasks

The next lesson covers message queues: how to decouple services and smooth out spikes.

Done reading?

Mark the lesson as read to move your track progress forward.

Go through it with an AI agent

The agent explains anything unclear in plain words, gives you 2 labs for this lesson and drills you on interview questions. $49 one-time, lifetime access.

Get access for $49

Tell the agent: use MCP izi, give me lesson data-basics-04-redis-basics