Skip to main content
Why YAGNI Began
Back to blog

Why YAGNI Began

At different companies, Rachel and I each spent about three years watching clean codebases become harder to change. We started YAGNI after seeing the same pattern despite differences in company size and domain: engineers did not get worse, but code accumulated things that should have been removed and were not.

This observation is hardly new. Every engineer with five or more years of experience has encountered it. It took us longer to pinpoint the real bottleneck: nobody lacked awareness of the dead code, but nobody had time for the verification needed to remove it safely.

The Problem We Experienced

In practice, the situation looked like this: you work on a backend service and need to change a utility function called from 40 places across the codebase. You inspect the callers. Perhaps 25 look live; the other 15 sit in modules you have never worked in and do not recognize. Are they live, dead, or part of a feature that shipped two years ago and then pivoted? You do not know.

That leaves two choices. Investigate, despite not having the time: grep for the modules, inspect git history, ask a senior engineer whether they remember the modules' purpose, and read the surrounding code. Now an hour has gone into a change that should have taken 20 minutes. Or skip the investigation and change all 40 callers, including possible dead ones. That takes longer and adds diff noise, but it is safe in that nothing breaks.

Both choices are poor. One spends unbudgeted time investigating; the other creates unnecessary work. Dead code does not stop you from shipping, yet it charges a constant tax on every change to the surrounding code.

Why Existing Tools Fell Short

Before YAGNI, we examined the available tools. Static analysis tools such as Vulture for Python and deadcode for Go identify candidates. Coverage tools point to zero-coverage files, while Code climate tools rate code quality. None completes the process.

The gap remains consistent: tools identify candidates, but turning one into a verified, safe deletion requires work they do not perform. You still need to check for calls through reflection or dynamic dispatch, evaluate the coupling blast radius, run tests, write the PR, and get review. The tool removed 5% of the work from your plate, leaving 95% unchanged.

We began prototyping YAGNI in early 2024, working nights and weekends while both of us still had jobs. The first prototype was a Python tool for Python repositories that built a basic call graph and produced a candidate list. We ran it against two codebases we could access. The lists were long and had a non-trivial false positive rate. We soon understood that a better list would not fix the problem.

Choosing to Build an Agent

Our direction changed after watching an early test user work through the candidate list. He spent about 45 minutes examining the first 20 candidates, then quit. He said something like: "I know most of these are probably dead but I can't trust any specific one without doing the same investigation I'd have to do anyway." The tool had not lowered his cognitive load; it had assigned him a different task instead.

That conversation led us to the agent model. We began asking what would let an engineer trust a PR proposing a deletion instead of a list proposing a candidate. The required quality bar was entirely different: not a candidate with a confidence score, but a proposal carrying evidence. Here is the call graph analysis, the production trace window, the test result, and the assessment of what else might change if the code is removed. That evidence package lets an engineer review a proposed deletion in five minutes rather than 45.

What We Are Building Toward

We are not trying to remove engineers from the deletion process. An engineer should review every proposed deletion, particularly when first using a new tool on a codebase they care about. Our aim is to remove the investigation that now lies between "we know we have dead code" and "we are confident enough to delete it."

We are also candid about the limits. YAGNI is conservative by design and does not suggest removal when it cannot fully analyze the code. Dynamic dispatch through unknown interfaces, reflection-based invocation, and callback registration patterns outside our recognized set go into medium or low-confidence tiers and require human review before any change. This caution means we miss some dead code. We would rather miss it than suggest wrong deletions.

We started YAGNI because we had experienced the problem ourselves and found no tool addressing the real bottleneck. Finding candidates was not the bottleneck; the verification work between candidates and commits was. We are building toward moving as much of that work as possible off the engineer's plate, one high-confidence deletion at a time.

Marcus joined us in late 2024, and we have built together since. We are independent, building the product in Denver, and running an early access program for teams exploring large codebases with us. If you face a similar problem, we are glad to talk.

Try YAGNI on your codebase. Free plan, no credit card required.

Get Early Access

More from the blog

View all articles