The claim you hear everywhere that "AI makes software cheap" is wrong in most of the ways that matter. What AI makes cheap is implementation: the act of turning a decision into working code.
Everything around that act has kept its old price, and so far AI models still haven't delivered "intelligence too cheap to meter" (they meter it quite well, and charge accordingly). Someone still has to decide what the system is supposed to do, define how the pieces fit together, draw the security boundaries, and judge whether the thing that came back actually works. An agent can now write an implementation, rewrite it, produce four alternatives, and throw them all away for relatively little cost. Judgment, taste, and experience still cost what they always cost.
That mismatch is the central economic fact of AI-assisted development. Agents can produce code far faster than humans can meaningfully evaluate it, and most of what they produce will be plausible but mediocre. Some of it will be subtly wrong. Some will solve the local problem while quietly damaging the system around it. And buried in the flood, every so often, will be an implementation better than the one you would have written yourself. The potential is real, but only if we stop treating every generated artifact as a finished piece of work awaiting human approval, one careful reading at a time. (I am mostly writing this essay to myself. This is hard for me to hear.)
To see what an alternative could look like, we should start somewhere altogether unexpected: with rocket engines.
Two ways to buy confidence
One of my favorite documentaries of all time (every engineer should watch it) is called Cosmodrome. It tells the story of the engines built for the Soviet N1 lunar program, and underneath the Cold War history is a contrast between two ways an engineering organization can operate and come to trust a complex machine.
Apollo bought its confidence the traditional, expensive way. The United States had money, industrial depth, armies of specialists, purpose-built test infrastructure, and a political mandate to reach the Moon by the end of the decade, before the Soviets, without killing astronauts on national television.
So NASA poured almost all of its resources into a vast preflight apparatus: modeling, review, documentation, component qualification, static firing, integration testing, mission rehearsal. It built facilities specifically to fire Saturn V engines and stages, and the flight hardware was static-tested and certified before it ever reached Kennedy Space Center. (NASA History) Apollo 4 was the first "all-up" test of the complete three-stage Saturn V, an aggressive flight-test strategy that combined systems NASA's earlier practice would have flown incrementally. (NASA) That aggression rested on an extraordinary foundation of ground work. The launch was still a test. It was just a very expensive test that the institution had arranged and very much expected to pass.
The Soviet program had brilliant engineers and little else. They didn't have the funding, the infrastructure, the coordination, or the schedule control. So they leaned on the one resource they did have, and at the engine level that meant direct contact with hardware. Build, fire, inspect, modify, fire again. Nobody read the welds, they pressurized them. Less simulation, more ignition: fire it up, see if it explodes, fix what broke, do it again, baby. And the process worked, at least at the component level. Boris Chertok's history of the program records that the N1's NK-15 first-stage engines achieved substantially higher chamber pressure and specific impulse than the Saturn V's F-1. (Chertok, Rockets and People Vol. IV) These were sophisticated engines built by people who had learned to use failure as an input and a guide.
The N1 also shows exactly where the approach runs out. Its first stage, Block A, clustered thirty of those engines into a single system of staggering complexity, and that complete stage was never static-fired on the ground. The reliability of the whole was supposed to follow from the reliability of the parts, but individual engine firings could not reveal the interactions among engines, plumbing, structure, wiring, and vehicle dynamics. Chertok later described each N1 launch as walking into a minefield without a minesweeper. (Chertok) The Soviet engineers built superb components, but they didn't build a way for the integrated system to fail cheaply before flight. All four N1 launches ended in failure, and the program died.
The lesson is not that the Soviet program was better than Apollo (it wasn't), and not that one side was reckless while the other was careful (both did their best inside their constraints). The useful contrast is narrower. Apollo converted resources into preflight confidence. The engine shop converted repeated contact with hardware into knowledge. Apollo could afford to surround every launch with an institution designed to make failure unlikely. The engine shop made failure frequent, cheap, and informative instead.
The metaphor I care about is not the N1 launch program (although it is fun, and comparing software engineering to literal rocket science makes me feel better about myself). It's the resource-constrained engine shop: many attempts, destructive pressure, direct observation, and no sentimentality about designs that didn't survive.
The slop is coming. Better models will improve the ratio of signal to garbage, but they will also increase the total volume of code being produced. Fighting to preserve a world where every implementation arrives singular, polished, and worthy of exhaustive human inspection is Apollo thinking applied to AI economics. It takes the output of an engine shop and feeds it into a process designed for one sacred rocket.
Do not bolt a slop cannon onto Apollo's review process and expect the humans to keep up. Steal the engine shop's willingness to generate, fire, break, discard, and try again. Learn from the N1 that component success does not compose automatically into a working system. Keep Apollo's seriousness about contracts, integration, and the places where failure is unacceptable. The point is not to choose the Americans or the Soviets. It is to put expensive certainty where meaning and integration live, and cheap destructive iteration everywhere else.
That is the actual inversion: generation should be liberal because selection must be severe.
Physics is an oracle. Software doesn't have one.
Conventional enterprise software development operates very much like the Apollo model, and for good reason. A serious organization tries to establish confidence before launch: design documents, architecture review, a human reading every diff, threat modeling, QA, staging environments that approximate production, controlled deployment, observability and rollback as the last line of defense. Software failures leak customer data, corrupt databases, and move money incorrectly, so the whole apparatus exists to catch problems while they are still cheap.
But notice the assumption buried in that process: implementation is expensive. When an engineer spends two weeks producing a change, it makes sense for other humans to inspect that change carefully. The implementation is a scarce artifact, and the branch and the pull request exist to protect it, refine it, and eventually bless it.
The engine shop treats the implementation as something much less precious (a candidate). The engineer doesn't have to anticipate every defect before the engine reaches the stand. The engine is fired, pressure is applied, and the result is evidence. A design that fails is not rationalized or preserved; it is diagnosed, modified, or scrapped. This is not less discipline than Apollo. It is discipline relocated out of preflight analysis and committee review and into the quality of the test environment, the instrumentation of failures, the speed of the loop, and the willingness to throw things away.
The relocation works for rockets because rockets live in a universe with an external judge (physics, baby). A combustion chamber either holds pressure or it doesn't. A turbopump either keeps spinning or tears itself apart. Heat, vibration, and fluid dynamics do not care how persuasive the design review was. The universe is the oracle, and it works for free.
Software has no equivalent, and this is the place where our otherwise perfect metaphor breaks. A program can compile and be useless. A service can satisfy its API contract while implementing the wrong business rule. A database can remain perfectly consistent while faithfully storing a wrong interpretation of the world. A test suite can be green because it encodes the same mistaken assumption as the code it tests. Correctness in software depends on intent, and intent often exists nowhere but in the heads of the people building the system. You cannot generate a mountain of code, apply pressure, and trust reality to select the right implementation, because in software there is no "reality" standing by to do the selecting.
The tempting response (and the one I see most often in blog posts and B2B SaaS pitches) is to manufacture the missing oracle. Mandate exhaustive tests, perfect simulations, formal specifications, a complete executable model of everything the system should and shouldn't do. But that is a woefully naive premise, and even if it were possible (it almost always is not), a complete oracle for a complex system is usually harder and more expensive to build than the system itself. If you could fully specify every valid behavior, every security property, every business decision in advance, you would already have done most of the engineering. A resource-constrained team cannot build Apollo's software and then build a second Apollo to prove the first one correct.
What a resource-constrained team can do (and the constraint here is qualified human developers in addition to time and money) is use the hard judges already lying around. Software has no single physics, but it is full of local analogs (if you squint real hard at least): the compiler, the type checker, the database constraint, the transaction, the interface definition, the state machine, the permission boundary, the resource limit, the sandbox. None of these can tell you whether you built the right product, but each one can make a whole class of wrong implementations fail mechanically, immediately, and without a human reading anything. The goal should not be one perfect oracle. The goal should be to arrange the system so that generated code collides with as many hard, cheap, existing oracles as possible on its way in.
Those mechanisms do not all provide the same kind of confidence. A compiler, type system, schema, state machine, or database constraint is a judge: it rejects a class of implementation it knows to be invalid. A sandbox, capability boundary, or resource budget is a blast wall: it limits the damage from everything the judges failed to recognize. The judges make bad work easier to kill. The blast walls make the surviving mistakes cheap enough to learn from.
The bottleneck moves to reading
Here is what actually happens when you drop AI into the conventional workflow. A test fails, an issue is filed, an agent produces a patch, and a human reviews the patch. If the agent produces patches ten or a hundred times faster than the human can read them, the review queue becomes the throughput limit of the entire system. The bottleneck has moved from writing code to reading (and ideally understanding) it.
And reading may be the worst place for it. AI output is hard to review precisely because it is plausible. It looks clean, uses familiar patterns, and often passes the obvious tests. The reviewer has to reconstruct the agent's assumptions, hunt for the omitted edge case, notice the quietly weakened constraint, and verify that the agent solved the actual problem rather than making the symptom disappear. That is expensive cognitive work, and flooding a human with more plausible code doesn't produce proportional productivity. It produces review fatigue, apathy (LGTM, ship it), and eventually a reviewer who approves eight hundred plausible lines and meets the bug in production.
You can't fix this by throttling the agents down to human reading speed, which forfeits the whole advantage, and you obviously can't simply wave the code through unread (YOU ABSOLUTELY SHOULD NOT DO THIS, VIBECODERS. READ THE GODDAMNED CODE). That does not mean humans stop reading code. It means exhaustive line-by-line review of every candidate can no longer remain the default proof that software is safe. We will not read every line. We must remain capable of reading any line.
When an authorization boundary moves, the evidence contradicts itself, the performance numbers make no sense, the implementation touches a critical path, or the machinery reaches the limit of what it can explain, an experienced engineer still has to descend into the code and understand what actually happened. But forcing every routine candidate through that same manual scrutiny turns an agent fleet into a very expensive code-generation queue. The only remaining option is to arrange the system so that most bad implementations die before any human sees them, which is exactly what the engine shop does. Generation can be liberal because selection is severe.
Severe selection, though, requires the software to be judgeable, and here the design of the codebase itself starts to matter. A loose, dynamically shaped system gives an agent enormous freedom to be almost correct: it can invent a field name, ignore an invalid state, widen an input, return an unexpected shape, skip a permission check, or persist a record that is structurally plausible and semantically wrong, and the failure may not surface until three services and several user actions later. A tightly specified system drags those failures back toward the moment of creation. The type checker rejects the invalid combination, the RPC compiler rejects the incompatible interface, the database rejects the impossible row, the state machine rejects the illegal transition, the capability system rejects the unauthorized call, the monorepo rejects bad deps and bad versions. The implementation is forced to confess its misunderstanding early, to a machine, and atone for its sins instead of concealing them until a human or a customer finds them.
None of this makes the code correct. What it does is make more kinds of incorrectness mechanically visible, and that is the shift that matters. The AI-native codebase should be designed not merely to help machines write code, but to help machines prove code wrong.
Contract-first, implementation-disposable
At the dawn of large-scale software engineering, we behaved as if we knew better than to trust our employees. There were rigorous schemas and checks and contracts and bureaucracy (and so much XML). But the proletariat ultimately revolted, and for the last twenty (maybe thirty now?) years, mainstream software development has been increasingly optimized for human ergonomics. Dynamic languages cut ceremony. Schemaless databases made early iteration painless. Informal JSON APIs spared teams the friction of maintaining interface definitions. Rules that might have lived in schemas, generated clients, validators, or explicit state models migrated into application code instead, because humans were writing everything and boilerplate consumed human hours. A stack that let a small team move fast was worth more than one that encoded every assumption up front.
AI inverts the tradeoff, because AI's cost profile is the opposite of a human's. An agent does not get tired of writing structs. It does not resent schema migrations, exhaustive enum matches, generated clients, validation layers, or repetitive interface code. AI is cheap at ceremony. What AI is expensive at is ambiguity. An underspecified request gives an agent room to make decisions that are locally reasonable and globally wrong. An underspecified interface lets two agents independently invent incompatible interpretations. A schemaless data model postpones their disagreement until runtime, when it is most expensive to discover.
Which points toward a genuinely strange conclusion: the return of the late-1990s tight-ass contract, minus the late-1990s human cost. Not XML everywhere, not configuration sprawl, not bureaucracy for its own sake, but a healthy distrust of the implementer, made explicit everywhere it can be made to bite.
Languages whose type systems eliminate broad classes of invalid programs before they run: Rust's ownership model lets the compiler enforce memory safety without a garbage collector and turns many concurrency errors into compile-time failures. (Rust Documentation) Explicit service definitions instead of improvised network requests: gRPC uses Protocol Buffers as an interface definition language and generates typed clients and servers from it. (gRPC) Relational schemas as part of the executable definition of the system: NOT NULL, CHECK, UNIQUE, and foreign-key constraints let the database refuse invalid state rather than trusting every generated caller to remember every rule. (PostgreSQL) Workflows modeled as explicit state machines rather than constellations of loosely related booleans. And generated code granted narrow capabilities rather than ambient access to databases, filesystems, and admin APIs. Least privilege exists precisely to bound the damage that buggy or compromised code can do, and agent-written code should be presumed to be occasionally both. (OWASP Foundation)
The organizing principle underneath all of it: contracts should be durable, implementations disposable. The durable artifacts are the ones that define what the system means. The types, the schemas, the service definitions, the legal state transitions, the invariants, the permission model, the transaction boundaries. Everything inside those boundaries can be generated, rejected, rewritten, and replaced without ceremony. "Disposable" is not another word for "irrelevant." It is a property the system has to earn. Enough intent must survive in the contracts, tests, examples, policies, and evidence above the implementation that replacing the code does not mean erasing the design. If deleting the implementation deletes knowledge nobody preserved anywhere else, then the implementation is not disposable yet.
That division also tells you where human review actually belongs. A human should care intensely when an agent changes an authorization boundary, weakens a type, alters a schema, adds a legal state transition, or relaxes an invariant, because those changes expand the space of behavior the system permits. A human should not have to read every line of an implementation that stays inside an already-accepted contract and is mechanically forced to satisfy it. The contract is where human judgment earns its keep. The implementation is candidate material.
To be clear about the limits: no architecture makes bad software impossible. Contracts can be incomplete. Types can encode the wrong model. A database constraint can faithfully enforce a mistaken business rule. The goal is narrower and actually achievable: make broad classes of bad code impossible to express, impossible to persist, unable to cross a boundary, or immediately visible when they try. Do that, and the economics change. Agents can explore without a human blessing every attempt. Generated implementations fail against the structure of the system instead of accumulating silently inside it. Scarce human judgment concentrates where meaning is created, not where code is merely produced.
The old stack optimized for the cost of human authorship. The new one should optimize for the cost of machine-generated ambiguity. We spent twenty years stripping out ceremony so humans could move faster, and now that implementation is cheap and review is expensive, ceremony has become infrastructure. Strong types, hard schemas, explicit contracts, relational constraints, state machines, and capability boundaries are no longer bureaucratic drag. They are the pressure vessel that lets you fire ten thousand engines and only spend time on the ones that hold.
Part 2 is about the small practical problem with firing ten thousand engines: they have shell access to your laptop.