Skip to content

Chesterton's Fence and the Codebase

The itch to rip out weird, ugly code you don't understand is usually wrong. The rule that separates senior judgment from junior confidence: never remove what you can't yet explain the existence of.

By Mehdi8 min read
Share
On this page

The instinct to rip out the weird, ugly code you don't understand is almost always wrong, and learning to suppress it is most of what separates a senior engineer from a confident junior. The junior sees a gnarly nested conditional, a redundant-looking approval step, a data field nothing seems to read, and feels the clean, righteous urge to delete it. The senior sees the same thing and feels a different reflex first: someone put this here, and I don't yet know why. That gap — between the urge to remove and the discipline to first explain — is not a personality trait. It is a learnable rule, and it has a name.

G.K. Chesterton gave it one in 1929. A reformer comes upon a fence built across a road, sees no purpose in it, and proposes to tear it down. The wrong answer, Chesterton says, is "I don't see the use of this; let us clear it away." The right answer is: "If you don't see the use of it, I certainly won't let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it." The fence is evidence. Someone built it on purpose, at cost, to solve a problem you may not be able to see from where you're standing. Your inability to see the problem is a fact about you, not about the fence.

Why the ugly code is usually scar tissue

Here is the mechanism, because the principle is only useful if you understand why incomprehensible code tends to be load-bearing rather than random.

Code does not start ugly. It starts as a clean expression of the happy path — the flow the author imagined when they wrote it. Then it meets reality. A customer does something nobody predicted. A downstream API returns a status the docs swore was impossible. A race condition corrupts one record in ten million and someone spends a weekend tracing it. Each of these events ends the same way: a patch. A special case. An extra guard. A field added to carry state the original model had no slot for. The gnarly conditional you want to delete is the fossil record of every time the happy path met a hard edge and lost.

This is why ugliness correlates with importance rather than against it. The clean parts of the codebase are the parts reality hasn't stress-tested yet. The scarred parts are the parts that have survived contact. A function with six seemingly arbitrary special cases is not six failures of craft; it is six encoded lessons, each one purchased with an incident, a debugging session, or an angry customer. The knowledge is real. What's missing is the comment explaining it — because the person who added the fifth special case was exhausted, shipping a fix at 1 a.m., and never came back to narrate why.

I watched the medical version of this in clinical training. Every strange line in a hospital protocol — the double-check on a potassium dose, the rule that two nurses must independently verify a heparin drip — looks like bureaucratic friction until you learn it was written in response to a specific dead patient. Hospital procedure is scar tissue at civilizational scale. The redundant approval step your ops team wants to streamline may be exactly the same kind of object: a fence built the day after something went badly wrong, standing quietly on the road ever since.

The pivot is one giant fence problem

This generalizes past code, and the highest-stakes version is strategic rather than technical. When a company decides what to keep and what to throw away — in a refactor, a reorg, or a pivot — it is making a Chesterton's fence judgment about every asset it owns. The failure mode is the junior engineer's, scaled up: throwing away the thing whose value you can't currently see because it doesn't fit the new story.

I've argued that most pivots fail because they keep the wrong thing — founders preserve the shiny product and discard the hard-won customer insight that was the only real asset. That is Chesterton's fence run in reverse and at maximum stakes. The validated learning is a fence: unglamorous, easy to overlook, load-bearing in a way that isn't visible until it's gone. The reformer's confidence — "I don't see the use of this, clear it away" — is exactly the emotional state of a founder mid-pivot, high on the clarity of the new direction, liquidating the one position that was actually in the money. Same cognitive error, four orders of magnitude more expensive.

How to investigate a fence, cheaply

The discipline is worthless if it's expensive, so here is the practical core: interrogating a fence is almost always cheap, and you do it before, not after, you reach for the delete key.

Start with git blame. This is the single highest-leverage move and it takes fifteen seconds. Who wrote this line, when, and — critically — what commit message and ticket came with it? A surprising fraction of fences explain themselves the moment you see the commit: "fix: handle null merchant_id when order created via legacy import." There's your reason. The field you thought was dead is keeping a class of real records from crashing.

Read the commit, then the ticket, then the incident. History is layered. The commit message gives you the what; the linked issue often gives you the why; and if the code followed an outage, the postmortem gives you the full story — the failure, the blast radius, the fix. Scar tissue almost always has a paper trail, because the pain that produced it was memorable enough to document somewhere.

Ask the person. If the author is still reachable — in the company, in Slack, in your network — one message resolves most ambiguity: "I'm looking at this special case in the settlement logic, do you remember why it's there?" Two things can happen. Either they say "oh, that was for the Ramadan traffic spike, leave it," and you've dodged a re-incident; or they say "honestly I don't remember, it was probably paranoia," which is itself signal, though weaker than you'd like.

When the trail goes cold, instrument, don't delete. Sometimes blame shows a reformatting commit, the author is gone, and the ticket system predates the current tooling. You're genuinely in the dark. This is the case people misread as license to proceed — I looked, I found nothing, therefore nothing's there. No. A failed investigation is the strongest reason to pause, not the weakest. Wrap the suspicious branch in a log line or a counter and ship that instead of the deletion. If the code never executes across a full business cycle, you now have positive evidence it's dead and can remove it with real confidence. If it fires once, at month-end, under load, you just learned why it exists without having to cause the outage yourself.

Telling scar tissue from genuine cruft

None of this means keep everything. The opposite failure — ossification, where no one ever removes anything because no one dares — is how codebases and organizations calcify into unmaintainable museums. Chesterton's fence is not a conservation law. It is a sequencing rule: understand, then decide. The investigation exists precisely to sort the two cases apart.

Scar tissue (keep, document) Genuine cruft (safe to remove)
Origin Traces to a specific incident, edge case, or customer Traces to a since-deleted feature, dead integration, or copy-paste
Still fires? Executes on real inputs today Provably unreachable, or guarded by a flag that's been off for a year
Reason Live: the condition it handles still occurs Dead: the system it protected against no longer exists
Right move Leave it, add the comment the author never wrote Delete it, with the evidence in the commit message

The point is that the investigation resolves either way, and both resolutions leave you better off. Find a live reason and you've saved yourself from re-suffering a solved problem — and you finally write the comment the exhausted original author didn't, so the next engineer inherits the lesson instead of the mystery. Find a dead reason — the integration it guarded was decommissioned, the customer churned, the migration completed — and you delete it with more confidence than the person who wrote it had keeping it. Cruft, correctly identified, should be removed aggressively. The rule only forbids removing what you can't yet explain.

The hardest cases are the ones that look most removable and aren't — and in my experience these cluster in one place. A schema is your strategy precisely because its load-bearing fields look like plumbing while quietly constraining what the business can become. The seemingly pointless data field is the canonical fence: a column nothing appears to read, that turns out to be the only record of a state your reporting will need eighteen months from now, that you can't reconstruct once you've stopped writing it. Building Kommerce for cash-on-delivery markets, half our schema looked baroque to anyone raised on Stripe's synchronous, card-settled model — states for partial acceptance, second delivery attempts, cash reconciled days after fulfillment. Every one of those "weird" fields was a fence around a real behavior of a real market. Delete them because they look redundant against a Western e-commerce mental model, and you don't get a cleaner schema. You get a data model that can no longer represent your actual business.

The rule, made operational

Institute one step and make it non-negotiable before any cleanup, removal, or "simplification": answer the question "why does this exist?" in writing, before you touch it. Put it in the PR template. Make it a line in the review checklist. The reviewer's job is not to approve the deletion; it's to confirm the author can explain what they're deleting.

The whole discipline compresses to a single inversion of instinct. Treat your inability to explain a thing as a reason to stop, not a license to proceed. The junior deletes what he doesn't understand because he doesn't understand it. The senior keeps what she doesn't understand for exactly the same reason — until she does. The confidence looks identical from outside. It runs in opposite directions.

Frequently asked questions

Isn't this just an excuse to never clean anything up? Codebases rot when nobody deletes.
The opposite failure — ossification, where nothing is ever removed because nobody dares — is just as fatal, and the essay says so directly. Chesterton's fence is not 'never change anything.' It is 'understand why it exists before you remove it.' That investigation resolves in one of two directions: the reason is still live, so you keep the code and finally document it; or the reason is dead, so you delete it with more confidence than the person who wrote it had keeping it. Either way you end up cleaner. The rule slows down exactly one thing: removal you cannot yet justify.
How much time should investigating a fence actually take? Most weird code isn't worth an archaeology dig.
Almost all of it is cheap. git blame plus the commit message plus the linked ticket resolves the majority of cases in under five minutes, because the reason is right there in the history. The person who wrote it is often still reachable in Slack for another five. Reserve real investigation — reading the incident postmortem, reconstructing the failure — for code whose removal has a large blast radius: anything touching money, auth, data integrity, or a core entity. Calibrate the dig to the cost of being wrong, not to the ugliness of the code.
What if git blame just shows a giant reformatting commit or a migration that erased the real author?
Then the cheap signal failed and you are genuinely in the dark — which is itself the answer. Inability to recover the reason is not permission to proceed; it is the strongest signal to pause. Wrap the suspicious code in logging or a metric and ship that first. If the branch never fires in a full business cycle, you now have positive evidence it is dead. If it fires once at 2 a.m. on the last day of the quarter, you just learned why the original author put it there without having to relive their incident.

Filed under Tech & Product. Building things people trust, at the level of the details.

Essays like this, in your inbox.

Thoughtful essays. No spam. Unsubscribe anytime.

Tech & Product

Your Product Needs to Be an Agent Skill, Not Just a Website

The next discovery layer isn't search or an answer engine, it's the agent's own catalog of callable tools. If a planner can't find and invoke your capability, you don't exist in the workflows leaving the human web.

7 min read
Tech & Product

An Agent Is Only as Good as Its Tools

Agent capability is bounded by the action space and feedback you expose, not the model's raw IQ. Most "our agent isn't smart enough" complaints are misdiagnosed environment-design problems.

8 min read