Delete code like you mean it
The bravest thing in a codebase is an empty space where something used to be, and most teams never get there.
Every codebase has a graveyard nobody visits: the legacy folder, the feature flag that's been false in production for two years, the helper imported in exactly one file that was deleted in 2022. We walk past it daily. We add to it. We almost never bury anything for good, because deletion feels like loss and addition feels like progress.
That instinct is backwards. Code is not an asset you accumulate. It is a liability you maintain — every line is something a future engineer has to read, test, and reason around before they can change anything near it. The most valuable commit I make in a given month is often the one with a green diff of zero and a red diff of four hundred. An empty space where something used to be is the rarest thing in software, because getting there takes more nerve than writing the thing did in the first place.
Why we hoard
We keep dead code for the same reason we keep boxes in the garage: deleting it requires a decision, and keeping it doesn't. The box might be useful someday. The function might be called by something we can't see. So we leave a comment — // keeping this just in case — and move on, having spent zero courage and zero thought.
The "just in case" is almost always a lie we tell ourselves. I have never once gone back to a commented-out block and resurrected it. When I genuinely needed the old behavior, I wrote it fresh, better, with everything I'd learned since. Version control already keeps the past. That's its entire job. Commenting code out instead of deleting it is refusing to trust the tool whose only purpose is to let you delete fearlessly.
The deeper hoarding is structural. A function that "might be used externally." An abstraction built for three cases that only ever saw one. A config option no customer has ever changed. Each one survives because nobody can prove it's safe to remove — and proving a negative is tedious, so we don't.
Make deletion provable
The cure for "I'm not sure anyone uses this" is not bravery. It's evidence. Bravery without evidence is how you take down checkout on a Friday.
Before I delete anything load-bearing, I want the codebase and the runtime to tell me the truth. Static analysis finds the symbols nothing references. Logging tells me what actually runs.
Don't guess whether a path is dead. Make it report in.
Ship that, wait a billing cycle, and the logs answer the question you were too nervous to answer yourself. Zero hits across a full month of real traffic is not proof of nothing — it's permission. Now the delete is a fact, not a gamble.
You don't earn the right to delete code by being brave. You earn it by making the risk visible enough that the deletion stops being brave at all.
The same discipline scales up. Want to kill a feature flag? First make it impossible to reach the off-path, then watch. Want to remove an endpoint? Return a 410 Gone for a release, count the screams, then pull it. Deletion becomes a sequence of small reversible steps that end in one irreversible, well-earned one.
The cost of keeping it
The team that never deletes pays in a currency that doesn't show up on any dashboard: hesitation. Every new engineer reads the dead branch and assumes it matters. Every refactor routes carefully around the abstraction nobody needs. Every estimate quietly inflates because the system is bigger than the problem it solves, and nobody can tell which parts are load-bearing.
I've watched a four-person team move slower than it should because the codebase carried a decade of "just in case." Not one of those decisions was wrong on its own. Together they were a tax on everything. The fix wasn't a rewrite. It was a quarter of disciplined subtraction — reading the logs, proving the negatives, and cutting. The product did exactly what it did before, with thirty percent less code to hold in your head.
- →Less code is fewer places for a bug to hide.
- →Less code is a smaller surface for a new hire to learn.
- →Less code is a change you can reason about completely, instead of mostly.
The win isn't aesthetic. A smaller system is a system you can actually hold in your head, and the systems you can hold in your head are the only ones you change with confidence.
Build the muscle
Make deletion a normal, scheduled, celebrated act — not a heroic one. Put a recurring slot on the calendar for it. Review pull requests for what they could have removed, not just what they added. When someone ships a minus-heavy diff, treat it like the gift it is, because the person who deletes the dead endpoint saves more future hours than the one who added it ever cost.
Most teams never reach the empty space because they're waiting to feel brave. Stop waiting. Gather the evidence, make the risk legible, take the small reversible steps — and then mean it. Cut the thing, push the commit, and watch how much lighter the next change feels.
