Skip to content

Design for Churn: What Changes When Code Gets Cheap

#ai-coding #code-review #prompt-engineering #self-hosting #developer-workflows

Design for Churn: What Changes When Code Gets Cheap ​

Writing code got cheap. That changes what's worth preserving. ​

Churn has been a dirty word in software for decades. Microsoft researchers showed relative code churn predicts defect density. Adam Tornhill's Your Code as a Crime Scene treats frequently changed, complex files as the first suspects. GitClear's research projected AI assistants would double the share of code rewritten within two weeks of being written and framed that as downward pressure on quality. The instinct is old: code that keeps changing was wrong.

That instinct comes from a world where writing code was expensive. Durability was how you got your money's worth. When a feature costs an afternoon instead of a sprint, the math flips. Rewriting something is often cheaper than carefully preserving it.

Look at the last six months of Forem, the open-source Rails forum that powers DEV. Of 563 commits, the most-churned file is app/models/article.rb, touched in 37 of them. The spam handler sits near the top too, at 13. Spam is a seasonal crop. Spammers change tactics constantly, and the code should churn right along with them. article.rb is different. When the core model gets dug up every week, new features root themselves there because it was the easiest place to plant them. The problem is unplanned churn in load-bearing places.

Key numbers Forem, six months: 563 commits. app/models/article.rb appears in 37. The spam handler appears in 13. Anthropic's Claude Code study: humans make about 70% of planning decisions and about 20% of execution decisions.

Codebases are gardens now ​

Software has always been described in building terms: architecture, foundations, scaffolding, load-bearing walls. Buildings stand still. Codebases are turning into gardens full of annuals. A gardener replants annuals every season. Nobody calls a tomato plant technical debt because it dies in October. The gardener's investment goes into what doesn't turn over: the soil, the beds, the irrigation, the oak tree in the corner. Good structure is what makes replanting cheap.

Code that churns a lot is disposable. Disposable doesn't have to mean sloppy. It can be well made. It just isn't made to last. Quality for an annual means it does its job, it's tested at its edges, and it can come out without tearing up everything around it.

The missing piece is a picture of what high-quality churn looks like. Our mental model of quality is tangled up with longevity, so we brag about code untouched for six years. Churn happens anyway, implicitly, and lands wherever is most convenient. That's exactly what the Forem numbers show: the core model absorbs the churn because nothing tells features where else to go.

Concrete moves:

  • Name the layers. Auth, feed sorting, and cache pipelines are perennials. The AGENTS.md file many teams already keep tells AI assistants to tread carefully there. That should be more than a warning label. It should be the shape of the codebase.
  • Put contracts at the edges. Interfaces, schemas, API specs, and behavior-pinning tests are the perennials. Whatever sits behind them can be rewritten freely, by a person or an agent.
  • Make removal cheap. The test of a good annual is whether you can pull it out without disturbing the bed. If something is meant to churn, it shouldn't have tendrils in everything.
  • Measure churn by layer. High churn in the fast layer is health. Churn in the slow layer is the alarm.

Anthropic's Claude Code study lines up with the split. The human makes roughly 70% of planning decisions and about 20% of execution decisions. The oak is where people still decide. The annuals are mostly agent actions, which is why replanting them is cheap.

Two failure modes show up when you try this. In Next.js, a feature can look easy to remove in the file tree and still be coupled through a shared cache tag. If it calls revalidateTag('posts'), that invalidates every cached entry carrying the tag, including ones used by unrelated parts of the app. Cache tags belong at the boundary, not just in folder structure. The second mode: the removal test has to cover stored data. If a fast-changing feature adds columns or writes new record types, deleting the code still leaves every future version of the core model responsible for those records. The cleanup path belongs in the feature contract, tested against a populated database, not a fresh install.

Prompt failure is a speech-act problem ​

You ask an LLM to use PackageX to do Y. It confidently writes code that calls a method that has never existed. For three years, the industry has diagnosed this as a memory defect. The weights are fuzzy. The model forgot the API