nine-fives · a backend survival game
Called nine-fives as a pun on five nines — 99.999% uptime, chased one wave at a time.
You're the engineer on call. Every wave throws real traffic at your chain of rented components — serve it or drop it, tick by tick. Not real hardware: a discrete-event sim, costs pulled from real pricing anchors. The surface is simplified; the tradeoffs aren't. Order matters, caches ignore writes, LBs pin hot keys, overprovisioning still costs you rank. Seven cards, then the shift starts.
Every backend answers a different question, so the game sorts traffic into three kinds — and punishes the wrong guess in seconds instead of one outage from now. Static diagrams never tell you that you cached the wrong thing; here the wrong box drops in front of you:
Each wave isolates one real failure mode — a burning hot key, flickering volatile prices, a static flood, a bot swarm — because combined failures teach nothing: when everything breaks at once you can't tell what killed you. Your orders state the modifier and the peak with its crush ticks up front. Size for the peak, not the average: averages lie, and the sim grades the crush.
Components run left to right, exactly as drawn. Each box serves what it can and forwards the rest; anything unserved past the last box drops. Order is architecture: limiter before cache, cache before database, queue before slow workers. Stack copies (×N) to widen a box; a load balancer splits cold traffic but pins hot keys to one backend; a fork gives reads and writes their own roads. New boxes need warmup ticks — plan for the cold start.
One engine runs the board and the headless CLI alike, under
go test — so a shape that survives here survives
everywhere. The board can never promise what the engine won't
deliver.
Boxes can stand alone or berth on a rented host — shared rent, cheaper per piece. The trade is priced, not vibes: berths cost 15% less up front, extra regions pay replication tax, and a regional outage darkens every box berthed in that region together. Spread critical pieces across regions, or gamble for the savings and watch the sky. Every tradeoff lands as a number, not an opinion.
Every piece bills rent each wave, win or lose, and the wallet carries across waves — going broke ends the run, and re-runs bill upkeep again. The kth copy of a type costs k times the first, so spam gets expensive; metered boxes bill per working tick instead. This is deliberate: in production the bill arrives too, so overprovisioning survives here and still loses rank. Survival first, efficiency second.
Press RUN and watch the wave walk your chain tick by tick — cohorts fly, boxes absorb, forward, or drop, telemetry counting live. Slow-mo stretches a tick so you see where requests die; pause freezes the line; hold stops time while you think. Failure is unmistakable and immediate, and retrying rewinds free: losing has to feel safe enough to experiment, because the pedagogy needs corpses. Cascades included — death shifting load onto neighbors isn't bad luck, it's the lesson.
Score is honest arithmetic: kept share (served traffic, slow counting half, stale zero) times unspent share (budget left), times a hundred. A failed wave caps at 59, under 40 fails outright, S demands 90+. The debrief is generated from your run's own why-log — the same explainability the CLI needs for balance testing is what teaches you, naming exactly what killed you.
Hints (three per wave), snapshots for the AI, last-win rebuilds — and when ready, interview mode against the clock, or sandbox with the wallet off.
shows once · a tour walks the buttons next