In the mid-'90s, I tracked my snowboarding season in a Microsoft Access database.
Not a spreadsheet — a database, with tables and queries and a little form I'd punch numbers into after a day on the hill. It computed cost per day, cost per run, cost per vertical foot, and vertical feet per day, per week, per season. That year I had a season pass and rode 75 days, which got my cost down to about $17 a day. I was very proud of that $17, and of the database, which I never touched again once the snow melted.
That database was disposable code, and it was glorious. Nobody's life depended on my vertical-feet-per-week. If a query broke, I shrugged and fixed it, or didn't. It existed to answer one person's idle question and then be forgotten. That is exactly what it should have been.
A skill set and a profession
Last summer Charity Majors wrote a piece called "Disposable Code Is Here to Stay," and it's been rattling around my head and my group chats ever since. Her argument, briefly: software is splitting into two modalities. Disposable code — prototypes, scripts, mocks, hobby apps, my snowboard tracker — is fine, will only get more common, and AI is genuinely good at it. Durable code — "the code that runs the world," bank transactions, medical results, satellite launches — is something else entirely. Her line that stuck: "Disposable software is a skill set; durable code is a profession."
She's right. And I'd add that the cost was never really in the writing. It's in the keeping — maintaining, extending, understanding, and trusting the thing for years. Charity points out that a two-year production track record beats any test suite, and anyone who's ever carried a pager knows that in their bones.
The Play-Doh cinderblock
Here's what worries me. We met this distinction at exactly the moment the whole industry left on a "vibe code all the things" world tour — and as vibe coding grows up and puts on a blazer (it's "agentic engineering" now, the grown-up name I keep hearing), the distinction is quietly dissolving.
AI-DLC, spec-driven development, Ralph loops, BMAD — these are real and useful, and I use them. But watch what they do: they take the habits of disposable code and apply them to durable problems. They're the Play-Doh cinderblock. If it's shaped like a cinderblock, it should behave like one, right? Surely. Except you skipped every bit of the heavy lifting that makes a cinderblock hold up a wall, and now you're trying to build a parking garage out of modeling clay.
Process maturity is not engineering maturity
"But wait," you protest. "My framework enforces tests, and all of them pass. My workflow runs an adversarial code-review before it commits, and a retro at the end."
Good. Genuinely — that's good stuff, and I want all of it. But notice what it does and doesn't buy you. Tests prove the code does what you said it should. Review catches the bugs you can see. A green pipeline is a beautiful thing. None of it — not one bit — tells you whether you designed something durable. You can have 100% coverage on a fundamentally bad architecture; the tests pass right up until the design assumption underneath them gives way. Process maturity is not engineering maturity, and we keep mistaking the one for the other, because the process is the part we figured out how to automate.
The agent that never says no
Because here's the thing none of those frameworks fix: your agentic engineering buddy will dutifully build whatever you ask for. Whatever. You ever see the Simpsons episode where they let Homer design a car? He demands everything — three horns, a giant bubble dome, tail fins, MOAR cup holders — and they build all of it, and the result is a magnificent disaster that bankrupts the company.

Every feature you asked for, and a few you didn't. The eager designer never said no.
I have genuinely tried to coach my assistants to play the adult in the room — to stop me when I go full Homer and start demanding cup holders. It never does. Not once, unless I nudge it with a direct question. These agents aim to please — you've noticed, surely — and just as "I don't know" isn't in their vocabulary, neither is:
"We could do that, Billy. But what you're asking for needs a complex left-join doing full scans across seven tables, with a round-trip API call on every keystroke as the user types into the field. You sure?"
That sentence is what I want from an agentic engineer. The real-world trade-off. The actual implication of the "design decision" — and I put that in air quotes on purpose, because a lot of these so-called "specifications" are pretty whimsical.
It invents its own bad ideas, too
And it's worse than just not pushing back on me. It will invent its own bad ideas and never mention those either.
A friend and colleague of mine — sharp guy — was off exploring this same agentic frontier the other day, rebuilding an old solar-energy analysis tool from scratch. No prior references, just a handful of sessions, and he was rightly amazed: the whole thing, recreated, working. Then one of his Lambda functions failed to make an outbound API call, and we opened it in the console to debug. And — what. What. What?! Not a hundred lines. Not five hundred. Not a thousand. Forty-five thousand lines of Node.js, minified into one wall with no line breaks. For a function that makes a single API call and puts the result in DynamoDB.
What happened? The agent, in its infinite wisdom and its powerful desire to be "self-contained," decided not to build a deployment package with its dependencies like a normal citizen. It simply inlined every dependency straight into the function body. All of them. What's not to love?
Here's the part that should keep you up at night: it worked. It ran. It almost certainly passed whatever tests existed. My friend stood up a functioning tool in a few sessions and was delighted — and he was right to be delighted — and also there was a 45,000-line minified monstrosity quietly running in the cloud that no human had designed, reviewed, or understood. Nobody decided to inline those dependencies. An eager machine did, to satisfy a goal it had set for itself, and it never said a word.
The missing skill is dissent
That's the gap. It isn't code generation — we have clearly solved code generation. The missing skill is judgment, and judgment's outward expression is dissent. An engineer worth the title tells you when your idea is expensive, or fragile, or just dumb. They tell you what a design will cost, in the currency of three-a.m. pages and migrations that can't be undone. They say no, and they say why. The frameworks can scaffold the ceremony of engineering — the tests, the specs, the reviews — but they cannot yet supply the part that was always the actual job.
So, the next time
The next time you board a plane, or slide into a CT tube, or just check your bank balance, take a beat and wonder about the software underneath. Was the control system designed, engineered, understood, rigorously tested, and tirelessly maintained by people who knew exactly what it would cost to get it wrong? Or was it tossed to an eager intern — silicon or otherwise — with a cheerful "you know what the customer wants, I expect to see the working product tomorrow"?
Disposable code is here to stay, and thank goodness. My snowboard database was perfect. But $17-a-day perfect and control-rods-down perfect are not the same kind of perfect — and the most dangerous thing about our remarkable new tools is how convincingly they make the first one look like the second.
(And yes: I wrote this with an AI's help, which is the joke and the point. The tools are extraordinary. They will just never tell you when you're being Homer. That part is still on us.)
