Setup guide · Tools and services
Redis
A local Redis running in Docker Compose with its data kept on a volume, answering redis-cli ping, and reachable from TypeScript and Python.
Exercises use Redis as the fast, shared memory next to an agent: caching model responses, rate limiting, queues, session state and short-term conversation memory. It runs fine in a container with almost no memory, and every exercise expects it on localhost:6379.
Redis or Valkey? Redis's own docs run Redis Open Source with the official redis image, and that's what answers use. Since Redis 8 it's open source again (AGPLv3 is one of its licences) and it bundles JSON, the query engine with vector search, time series and probabilistic types, which used to need Redis Stack. Valkey is the Linux Foundation fork of Redis 7.2. It speaks the same protocol, so every client and command on this page works against it. Use Valkey if you prefer its BSD licence, but the plain valkey/valkey image doesn't have the Redis 8 extras such as JSON and search.
Before you start
- Docker and Docker Compose installed and running.
- Port 6379 free. Stop a Redis you installed with Homebrew or apt, or use another host port.
- For the client code: Node.js, pnpm and TypeScript, Python with uv, or both.
1. Start Redis
Create a folder with this file:
services:
redis:
image: redis
command: redis-server --save 60 1 --loglevel warning
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:docker compose up -dimage: redisis the current release. Pin a tag such asredis:8only if an exercise says so.--save 60 1writes a snapshot to/dataevery 60 seconds when at least one key changed, so your data survives a restart. Without it, a cache is fine to lose; a queue is not.- No password. Protected mode is off in the image and the port is published, so anyone who can reach port 6379 on your machine can use it. That's fine on your own computer behind a firewall. Don't run this on a server with a public address.
For Valkey, change two lines and keep the rest:
image: valkey/valkey
command: valkey-server --save 60 1 --loglevel warningPut the URL in the project's .env:
REDIS_URL=redis://localhost:63792. Talk to it with redis-cli
The CLI is inside the container, so you don't need to install it:
docker compose exec redis redis-cli127.0.0.1:6379> SET greeting "hello"
OK
127.0.0.1:6379> GET greeting
"hello"
127.0.0.1:6379> SET temp "gone soon" EX 10
OK
127.0.0.1:6379> TTL temp
(integer) 10EX 10 gives the key a 10-second lifetime, which is how caches expire entries. Type exit to leave. With Valkey the command is valkey-cli.
3. Connect from TypeScript
Redis recommends node-redis, the redis package. ioredis is its older client, still supported and common in existing code, with a very similar API.
pnpm add redisimport { createClient } from "redis";
const client = createClient({ url: process.env.REDIS_URL });
client.on("error", (err) => console.error("Redis Client Error", err));
await client.connect();
await client.set("greeting", "hello from TypeScript", { EX: 60 });
console.log(await client.get("greeting"));
await client.close();node --env-file=.env src/smoke.tsAlways attach the error listener. Without it, a dropped connection crashes the process instead of reconnecting.
4. Connect from Python
uv add redisimport os
import redis
r = redis.Redis.from_url(os.environ["REDIS_URL"], decode_responses=True)
r.set("greeting", "hello from Python", ex=60)
print(r.get("greeting"))
r.close()uv run --env-file .env python smoke.pydecode_responses=True returns str instead of bytes. Leave it out when you store binary data such as packed embeddings. For asyncio code, the same package has redis.asyncio.Redis with the same methods.
Check it works
docker compose exec redis redis-cli pingExpected output:
PONGTroubleshooting
Error: connect ECONNREFUSED 127.0.0.1:6379 or ConnectionError. The container isn't running. Run docker compose ps in the folder with compose.yaml, then docker compose up -d.
port is already allocated. Another Redis is on 6379, often one from Homebrew (brew services stop redis) or another project's container (docker ps). Or map "6380:6379" and set REDIS_URL=redis://localhost:6380.
Python prints b'hello'. You left out decode_responses=True.
ERR unknown command 'JSON.SET' or FT.CREATE. You're on Valkey or an image older than Redis 8. Those commands come with Redis 8's bundled modules; switch to image: redis.
Going further
- Docker and Docker Compose, for compose commands and cleaning up volumes
- Postgres with pgvector, for data that must be durable and queryable
- Qdrant, for vector search at larger scale
Sources
- Run Redis Open Source on DockerDocs · RedisThe `redis` image, port 6379 and running `redis-cli` inside the container.
- redis image on Docker HubDocs · DockerSnapshot persistence with `--save`, the `/data` volume, and why the port is open without a password.
- node-redis guideDocs · Redis`npm install redis`, `createClient` and why node-redis is recommended over ioredis.
- redis-py guideDocs · Redis`pip install redis`, `decode_responses=True` and closing the connection.
- valkey image on Docker HubDocs · ValkeyThe drop-in open-source alternative and its `valkey-cli`.