Redis is an in-memory data structure server. Clients send commands over TCP (the RESP protocol), and the server keeps keys in RAM. A key holds a typed value: a string, hash, list, set, sorted set, stream, JSON document and more. Reads and writes usually take well under a millisecond, and every single command is atomic: the server runs commands one by one.
The data can be written to disk (RDB snapshots, AOF log), but Redis is designed around memory: the data set must fit in RAM, and the default setup (RDB snapshots only) can lose minutes of writes on a crash. Treat it as a fast shared state and messaging layer next to your main database, not as a replacement for it.
flowchart LR
API["orders-api<br/>redis-py"] -- "GET / SET / INCR<br/>RESP over TCP :6379" --> R[("Redis<br/>keys in RAM")]
W["worker<br/>redis-py"] -- "XREADGROUP / BLPOP" --> R
API -- "cache miss" --> PG[("PostgreSQL<br/>source of truth")]
R -. "RDB / AOF" .-> D[("disk")]
From Redis 7.4 the license changed to dual RSALv2 / SSPLv1 (source-available, not OSI open source)
March 2024
The Linux Foundation started Valkey, a BSD-licensed fork of Redis 7.2.4, supported by several cloud vendors
Redis 8.0 (2025)
AGPLv3 added as a third license option; the former Redis Stack modules (JSON, Query Engine, time series, probabilistic types) ship in the main distribution
For a test engineer the practical effect is small:
The data model, commands and protocol of Valkey and Redis are the same for everything in this guide. redis-py, redis-cli, fakeredis and testcontainers work with both.
Features added after the fork can differ (for example Redis 8 includes JSON and the Query Engine by default). Test against the same server and major version as production — managed services may run either one.
Other servers speak the Redis protocol too (Dragonfly, KeyDB); compatibility with less common commands varies.
dockerrun-d--nameredis-p127.0.0.1:6379:6379redis:8# pin a minor version in CI
dockerexec-itredisredis-cliping# PONG
# uv add redisimportredisr=redis.Redis(host="localhost",port=6379,decode_responses=True)r.set("myapp:greeting","hello",ex=60)# expires in 60 sprint(r.get("myapp:greeting"))# 'hello'print(r.ttl("myapp:greeting"))# 60
Examples in this guide were run with Redis 8.10.2 (redis:8 image), Redis 7.4.11 and Valkey 8.1.10 for compatibility checks, redis-py 8.1.0, fakeredis 2.38.0, testcontainers 4.15.0, pytest 9.1.1 and Python 3.13.