For a long time I had one hard rule as an engineering executive. If an engineer tells me: we need to completely rewrite this piece of code, I will reply: I’m gonna slap you on the hand. It was not “the code needs work.” Not “this module is a mess.” The word rewrite, the whole-thing-from-scratch move, got you slapped. My engineers knew it. Not everyone liked it.
I did soften, over the years. Partly because the rule was too absolute, and I knew it. Never say never. Partly because I am an engineer myself and I get the urge. You look at your own code from a year ago and there is nothing in it to love. And I had watched rewrites that worked, and studied why.
Then AI arrived and made the rewrite free, and it crystallized for me what my reflex had been guarding the whole time.
The ugly part is the point
Here is the thing. The beautiful part of your codebase is worthless. Not worthless as in bad. Worthless as in free. The clean core, the elegant architecture, the part you would put on a slide, that is exactly the part a model regenerates in an afternoon, because clean is what these things are good at. Ask for a tidy auth system and you get a tidy auth system.
What it cannot hand you is your spaghetti.
Because your spaghetti is not necessarily bad code. It is a change log. Every ugly patch in a mature system is a battle scar. The special case for the one customer whose data comes in malformed. A retry that looks ridiculous until you remember the vendor drops one call in a thousand. Each knot is a place where a clean idea met the real world and the real world won. The scar is the record of the collision.
I am not the only one noticing this, because AI is forcing everyone to look. An engineer writing up his own legacy system this year described it as a cabin that grew a new room every year with no blueprint. Another, trying to rebuild an app with a model, found the hard part was not the code at all. It was that years of tiny adjustments, every small nuance, were sitting in the old codebase and nowhere else. That is the asset. Not the architecture. The adjustments. Yet another part of the moat made of time.
I have my own favorite analogy: the code grows like a weed. That’s normal. That’s why programming is art, not a factory job.
The debt is the asset
This inverts the way we are conditioned to read a codebase, and the inversion is the whole game.
In recent years it became fashionable to say that mess in a codebase is technical debt. Something to pay down and apologize for. Under the old economics that was directionally correct, because writing code was expensive, so anything that made future writing harder was a real cost. AI broke that. When the writing is nearly free (well, just costs tokens), the clean code is the cheap part, because cheap now means regenerable, and the clean core is the most regenerable thing you own. Just have a clean spec. You can distill it from the product’s behavior, or better yet, from a competitor’s.
So value flips to whatever is hard to reproduce. And the hardest thing to reproduce in a codebase is not the elegant core. It is the accumulated mess, because reproducing it means re-living every collision that produced it. You cannot regenerate a history. You would have to go get bitten by all the same things again, one field incident or customer request at a time.
The industry has not caught up to this, and the current enthusiasm shows it. The pitch of the year is that AI finally made the rewrite affordable, so all that messy legacy that used to be too expensive to touch can now be regenerated clean. Finally, goodbye COBOL! Gartner has enterprises defaulting to AI modernization by 2027. Vendors quote it by the line, a few dollars where it used to be many. The framing is that the mess was always a liability and now you can finally afford to be rid of it.
That framing has the sign backwards. The mess was the only part with a high replacement cost. The clean code was always the commodity. We just could not see it while both were expensive.
Sometimes you burn it down
Now the honest part, because I have witnessed righteous rewrites myself.
At F5 the team rewrote BigIP. Not because it was ugly. Because the implementation lived in the kernel of a FreeBSD box, and the kernel was the wrong place for it. Every new feature had to fight the substrate, and feature velocity was dying. That was the real trigger for a rewrite, not taste. It is when the collisions have piled up in a structure that can no longer take the next one. The mess had stopped being able to grow.
Notice what that rewrite did. It did not throw the log away. Everything BigIP had learned about traffic, about the edge cases, went into the new thing. It did not come free. Feature parity with the old product took a while.
Later, building SSL VPN for Cisco, I did a clean-sheet implementation, and it came out better than what I had built before. People assume that proves the clean sheet wins. It does not, and the reason is specific. That Cisco box was an embedded system with no real operating system under it. I could not have reused the old code if I had wanted to, and I did not want to, and it would have been illegal anyway. So the team built it from scratch, from first principles. But it came out better for one reason only. We already knew where the bodies were. I had collided with SSL VPN reality once, and I carried that knowledge in my head into the second build. The artifact was fresh. The log was not. That is why the product reached the top right of the Gartner quadrant.
That is the whole rule, stated cleanly. A rewrite is legitimate when you move the memory into a better container. It is arson when you keep the container and burn the memory. F5 moved the memory out of a dying kernel. At Cisco I carried the memory into a new environment. Both kept the thing that mattered.
What the AI rewrite does
The AI rewrite, the one everyone is being sold, is the mirror image of both of mine. It keeps the container and burns the log.
It clones the shape you can see. The UI, the visible behavior, the surface. And it starts the collision clock over at zero, because the thing writing it has collided with nothing. It has never been paged at 3 a.m. by your system. It knows the architecture and none of the scars.
There is already a genre of write-up about how this goes. One engineer let a model refactor a payment service that moved a couple million dollars a day. The original authors were long gone. The tests passed, all zero of them, and the result looked clean and modern and reasonable. He shipped it. Production came apart. The clean version had quietly dropped one of the ugly branches that was holding something up, because from the inside that branch looked like exactly the kind of ugly wart you would remove. It was not a wart. It was a scar, and the model could not tell, and neither could he, because the man who put it there had left.
That is the pattern. The rewrite passes the demo on the same day it commits the amnesia, and the two look identical until the world shows up.
I have written before that the demo is cheap and the finished product is not. This is the same coin, other face. The product is expensive because it is made of remembered collisions, and a rewrite is an excuse for forgetting them.
The tell is that the people doing this well already know it. The good modernization work does not start by generating code. It starts by generating understanding, reading the old system and writing down what it does before touching anything. Describe the behavior, and the intent, and the corner cases. Not the pixels. That is the same move as F5 and Cisco in slow motion. Extract the log first, then rebuild. The teams that skip that step and just ask for a clean elegant version are the ones writing the incident reports. Document first approach also works really well with AI.
The part I still cannot resolve
Here is where I have to be honest, because my own examples cut into my own thesis.
The mess is not sacred. My Cisco build proves it. A better container, made by someone who holds the collisions, beats the old spaghetti every time. So the value was never the specific tangle of conditional statements with the branches for different customers. It was the history of the incidents and customer requests that tangle recorded, and the tangle is just the default place that history ends up stored. Move the history somewhere better and you win.
And not all mess is memory. Some of it is rot. The infamous copy-paste. Different implementation of the same thing. A shortcut made by someone who did not quite understand the logic of the framework. The uncomfortable fact is that from the outside, scar and rot look the same. A dense patch of conditionals could be twenty years of hard-won truth or could be pure sediment. Studies of technical debt keep finding that most of the pain comes from a small slice of the modules, which means most of the mess really is disposable and a minority of it is priceless, and they are interleaved, and nobody has a clean way to say which is which.
Often the person who wrote it cannot tell either. Which is exactly why this asset gets destroyed so casually now, passing unit tests with flying colors.
There is a gentler version of this. It is called refactoring. It is a crutch for the fact that you can never get the class hierarchy right up front, so you reshape the code as you learn, without throwing away what it already knows. AI finally got pretty good at it. I learned it firsthand. That is the safe move, and it is the opposite of the rewrite. Refactoring keeps the log.
So my old rule was wrong. Too absolute. You do sometimes rewrite, and I have. But the instinct under the rule was sound, and I could not have told you why through most of the years I enforced it. I was not protecting the code. I was protecting the memory in it, and slapping down the one move most likely to erase that memory before anyone checked what it knew.
The hard question was never whether to rewrite. It was whether you can tell the scar from the rot. Almost nobody can, all the time. Least of all the neural network behind a Claude Code instance, offering to make the whole thing pristine.

