The Router My Colleague Showed Me
I first noticed it in passing. Colleagues had it open during work — a dashboard I didn’t recognize, a dropdown with more providers than I’d ever seen. I didn’t ask right away. Just filed it away as something to look into.
It was 9router.
I clicked through the GitHub repo. Readme. Screenshots. A dashboard with 40+ providers in a dropdown. Fallback chains. Format translation. Token compression.
My first thought: this is too much.
I already had OpenCode. It worked. Sure, I’d been hitting the subscription cap three weeks into every billing cycle, watching the spinner hang while the rate-limit error loaded. But that was a subscription problem, not a tooling problem. I could live with it.
I closed the tab. Went back to the auth bug.
A week later, it happened again. 1am. Deploy waiting. OpenCode Go had hit its $60 monthly cap. I was staring at a rate-limit error, thinking about how much work I still had left.
The fallback providers existed. They were right there in the account settings — a list of free tier options I’d never configured. I’d been treating them like a joke. A backup for emergencies. Something I’d get around to someday.
When you hit your paid subscription limit three weeks in, having fallback providers isn’t optional — it’s the difference between shipping a feature and waiting for the reset date.
That night I went back to the 9router repo. Read it again, slower. The 40+ providers stopped looking like noise. They started looking like redundancy. The format translation — converting between OpenAI, Anthropic, and whatever new provider dropped that week — started looking like the thing I’d been manually copy-pasting prompts to work around.
The overload I’d felt before wasn’t complexity for its own sake. It was the thing I didn’t know I needed until I needed it.
I forked it that weekend.
And then I couldn’t stop.
The monorepo was the first thing I tackled. Next.js monolith, routing engine and dashboard tangled together. I wanted to understand what I was actually running.
So the monorepo split became the first change after forking: the API server (Hono) got its own workspace, the dashboard (Next.js) another, the CLI got esbuild bundling. The best way to understand something is to take it apart.
See The Tools I Built Around OpenCode for what led here. See What I Changed in 9router for what happened next.
Sources: OpenCode Go documentation ($10/month, $60/month usage budget across three rolling windows: $12/5h, $30/week, $60/month)
Thanks to Mahardicka Nurachman and Valerian Dwi Purnomo for showing me 9router.