Skip to content
5 min read

Cheaper to build than to buy

The build-versus-buy line moved. Weird, exact internal tools moved with it.


Kira is a self-hosted Jira-ish tracker I built for myself, which is the sort of sentence that used to sound like a warning sign. A mature adult hears “I built my own issue tracker” and checks for the exits.

But the old warning was built on old economics. Building a competent internal tool used to mean weeks of design work, months of backend glue, and a grim little permissions system. Buying the tool was usually cheaper, even if it fit badly, because the alternative was slow and expensive.

That math is changing. Not for everything. Please don’t read this as a manifesto for rewriting payroll. But for a narrow internal workflow with one real customer and a weird shape, the cost of building has collapsed hard enough that the build-versus-buy answer can flip.

The actual problem

The problem wasn’t that I needed a project tracker in the abstract. The world has enough project trackers. I needed a human-readable map of AI-agent work.

I run a lot of AI coding agents in parallel. Dozens at a time, across projects, poking at bugs, writing tests, drafting docs, chasing screenshots, fixing the thing they broke while fixing the thing before it. This is useful, and a little alarming if you stop paying attention.

The bottleneck became my head. I couldn’t reliably remember which agent was working on which branch, what it claimed to have finished, what needed review, which sprint a task belonged to, or whether the release note had been updated. The agents could produce work faster than I could keep a map of it.

That’s the important sentence. I didn’t need better project management ceremony. I needed a board I could read, maintained by systems that were already doing the work.

Why not Jira or Linear

Jira and Linear are good products. They’re also built, sensibly, for human teams. They assume people log in, click around, move tickets, comment in prose, and attend the rituals that make the board mean something.

That wasn’t my use case.

Per-seat pricing gets silly when the “users” are disposable agents. Setup friction matters when the thing I want to track is narrower than the setup itself. Most defaults are aimed at social coordination: teams, assignees, inboxes, views, cycles, roadmaps. Useful, if you have humans. Noise, if your workers are processes with API keys.

I could have contorted one of those tools into the shape I wanted: a service account, some glue, half the interface ignored, and a pile of conventions pretending to be a system.

Instead I built the thing I actually needed.

The bit that matters

Kira has a normal web UI because I’m still, regrettably, a human. It has organizations, projects, sprints, milestones, labels, tickets, comments, documents, webhooks, audit logs, work logs, velocity reports, and burndown snapshots. Tickets get keys like KIRA-42. Epics are tickets. Milestones are the roadmap primitive.

The important part is that Kira ships an agent-facing API.

There’s a machine-readable guide for supported automation workflows. It keeps the contract grounded against the real API source instead of becoming a stale wiki page I have to remember to update.

That changes the maintenance model. I don’t keep the board accurate by becoming the project-management clerk for my own automation. The agents log their own work. They open tickets, move tasks, and write release notes into Documents as part of the work.

My job is to read the board and make decisions. That’s the part humans are still decent at, on our better days.

Boring on purpose

The architecture isn’t clever, which is one of the few nice things I can say about it without lying. It’s a TypeScript monorepo: @kira/api for the Express server, @kira/web-app for the React 19 / Vite / Tailwind v4 SPA, and @kira/shared for types and enums. It uses SQLite through Prisma, and in production the API serves the compiled web app as static files.

Auth is similarly unromantic. Local JWT auth with refresh-token rotation, or Clerk / Google OAuth in production. Both modes present the same req.userId because every auth system eventually becomes plumbing if you’re lucky.

The domain model is the usual tracker furniture: projects with short keys, tickets with types like STORY, BUG, TASK, and EPIC, comments, labels, sprints, milestones, work logs, documents, webhooks, and audit logs.

This is exactly the kind of software I’d have been embarrassed to build by hand ten years ago. Not because it’s impossible, but because it’s too much surface area for a personal workflow. You’d spend so long assembling the table stakes that the original itch would heal.

Now the boring middle is cheap. Not free. Cheap. Cheap enough that a weekend can buy a tool with the right nouns, the right API, and no subscription screen asking how many synthetic coworkers I’d like to invite.

The new line

The old build-versus-buy question was usually decided by labor cost. Could you justify spending engineering time to avoid a SaaS bill? Usually no. The bill was annoying, but the engineering time was worse.

AI changes that calculation in a lopsided way. It’s much better at generating the standard parts of small software than it is at deciding what should exist. Once I know the shape of the problem, getting to a working internal tool is no longer a heroic act. It’s still engineering. You still have to read the code, run the tests, deploy it, and live with the consequences. But the activation energy is lower.

That makes weird, exact tools rational. A tracker for one person supervising a swarm of agents isn’t a venture-scale product category. It’s barely a category at all, just a use case with my fingerprints all over it.

That used to be the argument against building it. Now it’s the argument for building it.

The point isn’t “build everything yourself.” That way lies a private graveyard of half-maintained dashboards and a person explaining, with visible strain, why his calendar app has a plugin system. The point is narrower and more useful: the boundary moved. A tool perfect for a use case of one can now be cheaper than buying a general tool and spending your life politely ignoring the parts that don’t fit.