Build a real Redis from first principles, one architectural idea per step. By the end you have a working server that speaks the Redis wire protocol, survives restarts, fans out pub/sub, and replicates to standbys.
Every step is a runnable Python file you can read in one sitting. The previous step is always the starting point of the next.
| # | Step | New idea | Lines |
|---|---|---|---|
| 01 | TCP echo | Sockets, blocking IO | ~50 |
| 02 | RESP parser | The Redis wire format | ~140 |
| 03 | GET / SET | In-memory KV with dispatch | ~180 |
| 04 | Expiry | EXPIRE, TTL, lazy deletion | ~210 |
| 05 | AOF persistence | Append-only log, crash safety | ~250 |
| 06 | RDB snapshots | Point-in-time dumps + fork BGSAVE | ~280 |
| 07 | Pub/Sub | Fan-out + threading | ~220 |
| 08 | Replication | Master/replica log shipping | ~290 |
| 09 | Event loop | Selectors-based non-blocking IO | ~220 |
| 10 | Capstone benchmark | Measure the gap against real Redis | ~130 |
Each step folder ships with:
| File | Purpose |
|---|---|
server.py (or bench.py in step 10) |
The runnable code |
README.md |
Run instructions and what's new |
GUIDE.md |
Deep-dive on the concept that step introduces |
EXERCISES.md |
3-4 hands-on tasks to stretch your understanding |
- Python 3.10+
- uv (Python package manager)
- Optional:
redis-clifor talking to the server (any Redis 5+ client works)
git clone https://github.com/learnwithparam/build-your-own-redis-python.git
cd build-your-own-redis-python
make installmake 01-tcp-echoIn another terminal:
nc localhost 6380
> hello
< helloThat's your starting line. From here every step adds exactly one idea.
make 02-resp-parser
make 03-get-set
make 04-expiry
make 05-aof-persistence
make 06-rdb-snapshots
make 07-pubsub
make 08-replication
make 09-event-loop
make 10-capstone- Read step 1's GUIDE.md. Run the server, talk to it with nc. Do the exercises.
- Diff step 2's server.py against step 1's. See what changed.
- Repeat. The diff between steps is the lesson.
Every step looks like this:
# 1. Listen on a socket
# 2. Accept a client (or many)
# 3. Read bytes -> parse_resp -> handle_command -> encode reply
# 4. Send reply
def handle_command(frame):
name = frame[0].upper()
return COMMANDS[name](frame[1:])Variations on this shape carry you all the way to a multi-client, persistent, replicating server.
make testRuns an automated structural test suite. All assertions should pass.
- Not a production system. Use real Redis for production. We use JSON for RDB, no checksums, no Lua scripting, no clustering, no eviction policies.
- Not the fastest possible. Step 10 shows the benchmark gap and where it comes from. Closing it means re-implementing in Rust or Go (or rewriting hot paths in C).
- Not exhaustive. Real Redis has dozens of commands and many subsystems we skip. The point is the shape, not the inventory.
- A working Redis-shaped server you wrote yourself
- A diff-friendly progression that's easy to study
- A jumping-off point for porting to another language
- Learn to Build OpenClaw — Same shape, different domain. A Claude-Code-style personal AI assistant.
MIT. Take it. Fork it. Ship it.