~/runtimelab $ cat ./README

When Claude goes down, are you still an engineer?

Don’t let your core engineering skills depend on an API status page. Build your own Postgres driver, job queue or kernel allocator — nothing to install.

3 tracks · 22 challenges · 434 stages · 4 languages

runtimelab
DashboardCatalogRoadmapBlog
pass · 6moadada

~/runtimelab $ ls ./challenges

What you'll build

17 live, 6 coming soon · go · python · c · c++
All17Foundations3Learn9Systems17AI1
search 17 challenges…language: go ✕level ▾
./redisadvanced

Build your own Redis

An in-memory data store that speaks real RESP over TCP — up to replication, streams and MULTI/EXEC.

115 stagesgo · python · c
./http-parseradvanced

Build your own HTTP parser

Framing, chunked bodies, pipelining — and the request-smuggling cases where two parsers disagree.

20 stagesgo · python
./gitintermediate

Build your own Git

Blobs, trees, commits and a real clone over the wire.

47 stagesgo · python
./packet-journeyintermediate

Packet Journey

Decode one packet outward from the wire: Ethernet up to TLS, then a whole capture into flows.

20 stagesgo · python

tree ./careers

Backend & Systems Engineer

2 done · 1 in progress · 2 open · 1 planned

  1. Programming Foundations
  2. Learn Go by writing it
  3. Build your own Redis
  4. ·Backend Engineering
  5. ·Distributed Systems
  6. File Systems (C)
runtimelab
DashboardCatalogRoadmapBlog
pass · 6moadada
StagesInstructionsBoardFocus
Build your own Redis25 of 47 passed

Part 2 · Reading RDB

22RDB file header
23Read a string
24Read an integer
25Multiple keys
26Expiry
27Expiry, on read
28A sweeper
redis/26. Expiry→ current
instructionshints2/5guidedsolutiongodiscussionprogress7/12

Expiring a key

A real Redis lets you set a key that deletes itself. Your server must handle SET with a PX argument, and return a null bulk string once the key has aged out.

The tester waits 101ms for a 100ms expiry. Sleeping is not the interesting part — deciding when a key is gone is.

Two implementations pass this stage and only one survives stage 9: lazy expiry on read, or a sweeper. Pick deliberately.

$ $EDITORapp/main.go● saved · a1b2c3dCopy

files

app/

main.go

store.go

expiry.go

24 var expiry time.Duration
25 // PX is milliseconds, EX is seconds — mixing them
26 // up is the trap this stage is built around.
27 if len(args) > 2 {
28 switch strings.ToUpper(args[2]) {
29 case "PX":
30 expiry = time.Duration(ms)
▶ Run testsRun all & advanceoutputnotesruns

$ ./your_program.sh

Set with an expiry

Get before it expires

stage 26 passed · 2.4s · sandboxed, no network

runtimelab
DashboardCatalogRoadmapBlog
pass · 6moadada

~/runtimelab $ tail -f ./jobs/1382

Run testsRun all & advancerunning on runtimelab · sandboxed, no networkpassed
job #1382 — test output
→ job #1382 · stage 26/115 · "Expiry"
[setup] container up · gcc:14 · no network
[build] go build ./app … ok (1.8s)
[test] $ redis-cli SET mango 5 PX 100
[test] expected "OK", got "OK"
[test] $ redis-cli GET mango (+101ms)
[test] expected (nil), got (nil)
✓ stage 26 passed · 4.2s
[regression] stages 1–25 re-run · all green (11.4s)
next → stage 27/115 · "RDB file config"
✓ Stage passed — you're on stage 27 now.Next stage →
recent runs — redisone bar per run, oldest first · numbered by stage
runtimelab
DashboardCatalogRoadmapBlog
pass · 6moadada

~/runtimelab $ cat ./challenges/redis

Build your own Redis

11 parts · 115 stages
go ▾Continue — stage 26 →part 37/12

Part 1

Speak the protocol

PING, ECHO and a RESP parser

9/9

1–9

Part 2

Store something

SET, GET and a map that survives

9/9

10–18

Part 3

Make it forget

expiry, and deciding when a key is gone

7/12

19–30

  1. Passive expiry on read#passive-expirypassed 30 Jul 2026
  2. The PX and EX arguments#px-expassed 30 Jul 2026
  3. Expiry#expiryin progress
  4. 27RDB file config#rdb-config
  5. 28An active sweeper#sweeper

Part 4

Persist it

an RDB file you can actually load

0/14

31–44

Part 5

Replication

a replica that catches up and keeps up

0/28

45–72

7 of 12 passed · make it forget

Stage 26 · what the key actually does

t=0t=100mst=101msSET mango 5PX 100key lapsesGET mango→ (nil)lazily on read, or swept — your call

Every stage ships with the picture the prose is describing — drawn for the trap, not for decoration.

  • ./http-server
  • ./redis
  • ./request-journey
  • ./ringbuffer-go
  • ./tcpproxy-go
  • ./filechunker-go
  • ./uploadserver-go
  • ./backend-go
  • ./driver-go
  • ./varint-go
  • ./wal-go
  • ./learn-systems-c
  • ./http-parser
  • ./packet-journey
  • ./bpe-tokenizer
  • ./text-generator
  • ./foundations-py
  • ./foundations-go
  • ./foundations-c
  • ./learn-go
  • ./learn-python
  • ./learn-c
ls ./challenges

Pick something you already depend on.

A Postgres driver, a packet decoder, an HTTP parser that ends on request smuggling, a write-ahead log, a GPT tokenizer — and Redis and Git too. Every challenge is the real system, reduced to the decisions that made it — in Go, Python, C or C++. Browse the catalog

  • Four languages

    Go, Python, C and C++. Pick the one you know, or the one you want an excuse to learn.

  • Ordered into paths

    The roadmap puts the challenges in the order an engineer would meet them, so there is always an obvious next thing.

  • A new challenge every month

    The catalogue grows on a published schedule, and a pass you already bought covers everything that lands while it is live.

vim ./stage-7

Write it anywhere. Nothing to install.

No Docker, no agent, no setup. Every challenge is a private git repo we host for you: edit in the browser and press Run, or clone it and work in your own editor. How it works

  • Works on a Chromebook

    On a locked-down work laptop, on a machine you have never set up before. If it has a browser, it works.

  • Your code, in a repo

    Clone it, push to it, open it in VS Code. Nothing is stranded on one laptop and nothing is trapped in our editor.

  • The stage is the lesson

    A short page on what the real system does here, and a failing test that will not pass until yours does the same.

./run

Press Run. Watch it go green.

We compile your latest commit and drive the stage's pinned tester against it inside a sandboxed container with no network access, then throw the container away — and stream the logs back while it happens. Where the tests run

  • Sandboxed, no network

    The container that runs your code has no route out and holds no credential. It exists for one run and is destroyed.

  • Logs as they happen

    Build output, every assertion the tester makes, and what it expected — streamed, not dumped at the end.

  • Regressions stay honest

    Passing stage 40 re-runs the thirty-nine behind it, so a shortcut you took in stage 6 surfaces the day you take it.

cat ./progress

One stage, one idea, one trap.

Every stage is gated by the specific mistake a good engineer makes first — the boundary that belongs to the other band, the read that hangs on a perfectly healthy server. Hit it once, with a test that explains what it costs. See the roadmap

  • Diagrams, not decoration

    Each stage ships with the picture its prose is describing, drawn for the trap rather than for the page.

  • Help when you are stuck

    Hints one at a time, guided prompt paths, a reference solution once you have earned it, and the discussion for that exact stage.

  • Proof of work

    A public page for every challenge you finish, with the stages you passed and when — yours to link to.

22

challenges, live now

434

stages to pass

4

languages

3

tracks

$ mkdir my-redis && cd my-redis

Ready to build something real?

The first stages of every challenge are free to read and run. No install, no card, no subscription — see whether the format suits you first.