2026-09-14

Every Feature Needs an Exit

The dangerous thing about cheap code is not that agents will write bad features. It is that they will make every feature feel too inexpensive to refuse and too established to remove.

Addition is the easy decision

A new feature rarely arrives as a permanent burden. It arrives as a small request with an obvious upside. Someone can use it. The code is quick to produce. The demonstration works. When an agent can turn the idea into a polished change before the meeting ends, saying yes feels almost free.
The code is only the first cost. Once the feature ships, other behavior begins to lean on it. Navigation points toward it. Tests preserve it. Support has to understand it. Permissions, analytics, documentation, and data models start carrying its assumptions. A feature that nobody deliberately chose to keep can still become expensive to disturb.
Agents accelerate that accumulation. They remove the typing friction that once forced weak ideas to wait. Our position is that a factory which only makes addition cheaper will eventually spend its advantage maintaining decisions nobody would make again. Generation scales. Unless removal scales with it, complexity wins.

An exit is part of the specification

Every feature should enter with an exit contract. What outcome is it meant to change? What evidence will show whether that happened? When will the evidence be reviewed? Which condition means the feature should be removed? If nobody can answer those questions, the request is not small. It is an open-ended commitment hiding behind a small patch.
The contract also needs a map of what removal touches. Name the routes, stored data, permissions, events, interfaces, and downstream behavior the feature creates. Keep those edges visible. Deletion becomes frightening when nobody knows whether the feature is isolated or has quietly become a foundation.
This is product judgment, not cleanup etiquette. A person chooses which outcome matters and which trade is acceptable. The factory turns that decision into machinery every run can inherit. It can require the fields, create the observation, schedule the review, and refuse promotion when a change has no credible way back out.

Usage is evidence, not a verdict

A quiet dashboard can tell you that people are not reaching a feature. It cannot tell you why. Perhaps the feature solves no useful problem. Perhaps nobody can find it. Perhaps a small group depends on it for a rare but critical job. Counting visits is a signal. Treating the count as the whole decision is just governance by proxy.
Define the judgment before the numbers arrive. If the feature exists to reduce a recurring failure, observe that failure. If it exists to change a workflow, measure the completed outcome rather than the screen that was opened. Pair the signal with the consequences of removal, including data that must migrate and users who need another route.
Then make the review happen. A note that says revisit later is not a control. Give the contract an owner, a date, and a route that produces a decision: keep, change, or remove. The factory should surface the evidence and prepare the reversible action. A person should judge the consequence, not spend a morning reconstructing why the feature exists.

Deletion needs its own proof

Removing code is not the inverse of adding it. A feature can disappear from the interface while its jobs still run, its data still accumulates, and its permissions still grant access. A deleted module can leave callers, flags, dashboards, documentation, and operational alarms behind. The visible surface is often the smallest part of the exit.
Give removal the same production discipline as construction. Search for dependencies. Exercise the replacement path. Migrate or retire stored data deliberately. Prove that background work stopped. Watch the release for behavior the original map missed. Keep rollback available until the evidence survives real use.
Feature flags help only when they lead somewhere. A permanent off switch is still permanent complexity. The exit is complete when the behavior, its authority, its data obligations, and its supporting machinery are gone—or when the remaining pieces have an explicit owner and reason to stay.

Make removal routine

Teams avoid deletion because it is uncertain work with invisible rewards. The factory can change both conditions. It can preserve the original contract, trace dependencies, assemble the evidence, generate the removal plan, execute the repeatable checks, and watch the result. What used to require institutional memory becomes a governed route.
That route will remove human work too. Manually inventorying dependencies, carrying cleanup reminders between planning meetings, and checking routine removals are repeatable coordination jobs. Agents can perform them continuously. People remain responsible for deciding whether the outcome still matters and whether the consequences of removal are acceptable. That is a smaller, sharper job—not a promise that every current role remains intact.
Cheap creation should make you more willing to experiment, not more willing to accumulate. Ship the bounded attempt. Observe what it changes. Keep what earns its place. Remove what does not, before the next layer learns to depend on it. A software factory is not healthy because it can build without stopping. It is healthy because it can let go without fear.
In response to Bad code is kudzu by Vicki Boykis.