AI Made Code Cheap. Not Engineering.

AI has made implementation cheaper, but the rest of software engineering has not disappeared.

In this article

Everyone's a builder now. Product managers can prototype a workflow before engineering has estimated it. Founders can get an MVP running before hiring a team. An engineer can ask an agent for three implementations, try them, and throw two away without feeling guilty.

That part is actually useful. More people can try an idea before turning it into a full project.

The bit that gets skipped in demos is what happens after the demo works.

The code has to go somewhere. It becomes a repository, a pull request, a CI job, a package, a service, a dashboard, a cron, a database table, a permission model, and eventually something someone has to explain during an incident. Someone still has to review it, understand it, secure it, monitor it, debug it, pay for it, migrate it, or delete it.

AI made implementation cheaper. It did not make the rest of engineering disappear.

Where The Code Goes

The code does not stay in the chat window. More code means more reviews. More tests mean more CI load. More services mean more infrastructure. More internal tools mean more data models, permissions, and one more final_final_v3 workflow with a very important document attached.

A generated change can pass tests and still be expensive. It can add six database calls per request. It can keep a container running all month for a job used twice. It can create an abstraction everyone avoids six weeks later. Nothing explodes. The bill just creeps up, the system gets a little harder to reason about, and the next change takes longer.

That is the part people miss when they talk about code getting cheaper. The writing got cheaper. The surrounding work did not vanish. It moved into review, deployment, observability, security, ownership, and the cloud bill Finance asks about in the least fun Slack thread of the month.

AI also tends to repeat whatever the team already does. Good defaults get reused faster. Weak ownership creates more orphaned code. A messy release process produces more ways to be surprised. The tool doesn't know which shortcuts are required and which ones are just stale.

Existing Code Has A Backstory

Building something new with AI can feel almost unfair. Clean repo, no weird migrations, no half-remembered outage, no "temporary" interface from 2020. The agent gets room to pick patterns and keep them consistent.

Brownfield code is different. Editing it means arguing with history. You are not only changing files; you are touching hurried launches, abandoned rewrites, customer-specific exceptions, and environment variables nobody wants to touch.

The files show what is currently checked in. They rarely explain why the billing service still uses the old client, why the migration is split into three jobs, or why nobody removes the compatibility layer. That context may be in Slack, a ticket, a meeting note, or one engineer's memory.

This is where generated tests and fast patches can get a little too impressive. Agents love writing tests. Sometimes that helps. Sometimes the test asserts that a mock was called, copies coverage that already exists, or locks in an implementation detail nobody wanted to promise. The suite gets larger, CI takes longer, and nobody is more willing to ship because of it.

Fast fixes have the same problem. If an agent can patch a bug in minutes, rollback starts looking optional. But the patch lands after customers have already hit the bug. If the first change touched a schema, queue, cache, or permission model, another rushed change can make the state of the system even harder to understand.

So yes, the agent can read the code. The missing part is why the code is shaped the way it is, what has broken before, and which ugly bits are still there on purpose.

Parallel Agents Still Need A Driver

The worktree demos look pretty neat. One branch for the refactor, one branch for the feature, one branch for tests, all humming while someone explains how they became a 10x engineer.

Don't get me wrong, the setup works when a human is sequencing the work.

The mess starts when people assume agents can coordinate it themselves.

Developer A asks an agent to clean up a shared dependency. Developer B is shipping a feature that still depends on the current API. Both tasks are reasonable. They pull the same code in different directions.

The refactor agent changes an interface. The feature agent still needs the old behavior, so it adds back an escape hatch. The refactor agent returns, treats that as leftover mess, and removes it again. The feature agent later "fixes" it for the feature.

By merge time, the human is not only resolving files. They have to decide whether the cleanup waits, the feature adapts, or the dependency gets split. That decision depends on priority, ownership, release timing, and the meeting nobody wrote down.

Agents can follow types, tests, imports, and syntax. They usually don't know what the team is trying to do this week. Without that context, five branches can confidently undo each other's work.

The Part After The Demo

The "everyone is a builder" idea gets messier inside companies. Think of the internal tool you hate: the expense portal, the leave tracker application, the dashboard that times out right before export. Most people can imagine a better version.

Now imagine every team making one.

This can be good if the company has shared auth, data access, deployment paths, logging, and ownership. People can build better interfaces without inventing new infrastructure every time.

Without that foundation, every quick tool can become another database, permission model, source of truth, and production-ish app under someone's personal account. Finance has one version, Ops has another, Sales has a third, and suddenly everyone is asking why the "prototype" is in the renewal process.

The creator leaves. The workflow changes. Nobody knows if deleting it breaks something. What started as one afternoon of prompt-and-polish turns into recurring maintenance.

The same thing can happen in a normal engineering workflow. An agent can make a PR look finished: clean diff, tests added, tidy names, maybe even a nice summary. But polish is not the same as having lived with the decision. Someone still has to notice when the shortcut will become permanent, when the migration cannot be rolled back, or when the clean design is going to be miserable for support to explain at 2 a.m.

So the useful review is not just a last look at the PR. It needs to happen while the shape of the work is still flexible. That is when someone can say: make this smaller, use the existing service, add a rollback path, or don't turn this into a thing we now have to own.

All this doesn't mean people should build less. Build the useful thing. Replace the bad internal tool. Prototype the workflow. Let agents remove the boring parts. Just don't pretend the generated work is finished because it runs locally.

Before it joins production, someone should know why it exists, how to validate it, how to roll it back, and who owns it after the prompt is gone.

The better use of AI might be helping with that part too. I would rather ask an agent why a service still exists than ask it to generate another service. Which service depends on this queue? Why does this job run twice? What customer still hits the old endpoint? Who gets paged if this worker falls over? Today those answers live across dashboards, tickets, Slack threads, stale diagrams, and someone who remembers an incident from four years ago.

If agents can help connect those fragments, I want that more than another pile of generated code. Give me the agent that can answer those questions before I delete the wrong queue.