Skip to content
Muhammet Şafak
tr
Journal 9 min read

Fast from scratch, slow in a live system: the real cost of brownfield in the age of agents

Work an agent finishes in days takes a week inside a system that has been running for years — because there the cost isn't producing code, it's finding the rules and proving them.


Last week I did two jobs. The first was greenfield: I described what I wanted to an agent, read and corrected the plan it produced, then had it written step by step. A few days later I had a working, tested, deployed application. A few years ago the same job would have cost me weeks — I have no doubt about that.

The second was moving a single module — a CRM module — out of an old application and into a newer panel, inside a system that has been in production for years. In terms of code it was small: a handful of screens, a few tables, a few reports. It took a week.

Putting those two durations side by side produced the observation this post is about: we look for speed in the wrong place. What an agent made faster is producing code. In a system that has been running for years, producing code is the small part of the job; the large part is knowing that what you produced is correct. That part did not get faster.

Two jobs, two different bottlenecks

Let me define both terms clearly, because the rest of this post rests on the distinction.

Greenfield is work with no existing behaviour to conform to: you decide what “correct” means. The data model is a blank page, there are no users yet, and every decision can be reversed in a couple of hours.

Brownfield is changing a running system without breaking its behaviour. Here “correct” already exists — not the correctness you define, but the one the system has accumulated over years. And most of it is written down nowhere.

The difference isn’t difficulty, it’s where the knowledge lives:

GreenfieldBrownfield
What is “correct”?You define itThe system already defined it
Where is the knowledge?With you and whoever askedIn the code, the data, people’s heads
Cost of a mistakeReversibleTouches live data and users
Dominant costProductionVerification

An agent is a multiplier where the knowledge is with you, and an assistant where the knowledge is in the system. Same tool, two very different returns. I’ve written before about the same tool producing different results in different hands; this post is the same observation from another side — not the tool or the person, but the kind of work.

In brownfield you’re not moving code, you’re moving rules

When you relocate a part of a system that has been running for years, what you carry isn’t lines — it’s the business rules that have settled into those lines. Those rules hide in three places, and each one needs a different kind of digging.

The unwritten exceptions inside the code

In older, layerless code a rule sits in the middle of the flow as an if. Roughly like this:

public function updateStatus(int $id, int $status): void
{
    $customer = $this->find($id);

    // status can't change once the contract has expired — except for reseller accounts
    if ($customer->contract_end < date('Y-m-d') && $customer->type != 3) {
        throw new DomainException('Operation not permitted');
    }

    // 7 = archived; an archived record is left without an owner
    if ($status === 7) {
        $this->clearOwner($id);
    }

    $this->save($id, $status);
    $this->log($id, $status);
}

There are at least three business rules in those fifteen lines: an expired contract blocks changes, one account type is exempt from that rule, and archiving a record clears its owner. All three are real. All three are documented nowhere but here.

What stretches the job isn’t the number of such rules; it’s having to stop in front of each one and ask whether it is still wanted, or whether it’s the scar of something that happened years ago. In my case one turned out to be a contractual clause, one had been added to paper over an old bug, and one was the residue of a process nobody runs any more. The code states all three in the same tone, with the same confidence.

The implicit rules inside the data

The second hiding place is the database: rules that don’t appear in the schema but govern behaviour. What the numbers in a status column mean, whether a NULL field means “unknown” or “not applicable”, columns whose names no longer describe the data they hold.

You can’t learn any of it by reading the schema; you can infer most of it from years of accumulated data. What I do in practice is simple: for every ambiguous column I run a distribution over production data. The list of values a column actually takes describes its real domain more honestly than any document — and that list is what determines the constraints I put on the new side: enums, nullability, foreign keys.

The reasoning inside people’s heads

The third one can’t be searched anywhere. Code tells you what a rule is; why it was added is usually known only to people. So I collect questions in batches rather than asking them one by one, and put them in a few short conversations: “is this behaviour intentional?” One answer comes back as “yes, it’s in the contract”, another as “no, that was wrong to begin with”. The second answer is the only legitimate thing to fix during a move; everything else gets preserved.

Where an agent is a multiplier, and where it’s an assistant

This is not an “AI doesn’t work” post — the opposite. It helped seriously in the brownfield job too, but in three specific places.

What it made faster:

  • Mechanical transformation. Converting one shape into another — skeletons, routing, validation classes, the new equivalent of old queries — is almost entirely mechanical. Minutes rather than hours.
  • Reading code and extracting rules. Scanning the old code file by file to summarise which rules live where and which conditions depend on which fields. A day of reading finishes in a few passes. The result isn’t an answer, it’s a question list — but having the right questions in one place is valuable on its own.
  • Verification tooling. Throwaway scripts comparing old and new output for the same input, characterisation tests for critical flows, small tools pulling report totals from both sides and diffing them. Describing what my self-review setup speeds up and where it falls short landed in the same place: the benefit is in verification, not production.

What it didn’t:

  • Deciding whether a rule still holds. An agent can find a rule; it cannot tell you whether the rule is still wanted. That knowledge isn’t in the code — it’s in people. All the code holds is the fact that someone once wrote it that way.
  • Verifying. Making the new side look like it works takes five minutes; showing it produces the same results as the old one takes days. And deciding whether a discrepancy is a bug or “the old one was already wrong” is the slowest part of the job.
  • Cutover and coordination. Which evening to switch, who won’t be entering data at the time, what the way back looks like, what users get told. Not technically hard — but it takes up calendar.

The lasting lesson: an agent writes the common case very well but doesn’t see what is specific about the problem. In a system that has been running for years, the work is exactly that specific part.

An honest breakdown of the week

The approximate distribution of the example above, across five working days:

ItemTimeAgent’s share
Discovery, rule extraction, getting questions answered~1.5 daysHigh — it did the scanning, I made the calls
Writing the actual code~1 dayVery high
Parity verification~1.5 daysMedium — it built the tools, I read the results
Edge cases, reports, integrations~0.5 dayLow
Cutover, monitoring, fixes~0.5 dayNone

Condensed into one sentence: writing code was one day out of five. The other four went into learning what the code was supposed to do and proving that it did it. The item where the agent is strongest was about a fifth of the total.

In the greenfield job the ratio was nearly inverted: most of the time went into production, because there was no past to conform to. That’s why the two durations ended up so close.

How I estimate brownfield work now

The practical consequence of this observation was a change in how I estimate.

  1. Count unknown rules, not lines. “How many lines of code” doesn’t measure the size of brownfield work. The question that does: how many behaviours are there whose reasoning nobody knows? If that count is unknown, so is the estimate.
  2. Spend the first half day on discovery, then give the number. The output of discovery is a rule inventory: one line per behaviour — what it does, where it’s written, who can confirm it. The length of that inventory sets the estimate.
  3. Budget at least as much for verification as for production. In practice the ratio comes out around 1:1.5. A plan that skips this budget pays the difference in production.
  4. Write cutover as its own item. The job isn’t done when the code is; the switch, the monitoring and the first-day fixes deserve visible space on the calendar. Writing about which methodology I pick for which project led to the same place: under high uncertainty a plan sequences learning, not steps.

What I take from it

Don’t carry greenfield speed into a brownfield estimate. “We finished it in three days with an agent” is not a unit of measure for work inside an existing system. The bottleneck sits in different places: production in one, verification in the other.

“Couldn’t AI do this in two days?” The honest answer: writing the code isn’t two days, it’s one. But the job isn’t called writing code; it’s called relocating years of accumulated behaviour without breaking it. The part that got faster is a fifth of the work; the rest is still human.

One note in the other direction: the systems we ship in three days with an agent today will be the systems someone spends a week on a few years from now. That’s why, even in the fast job, I try not to bury rules in the middle of the code — and to write the reasoning into the commit message and the tests at minimum. We are producing tomorrow’s brownfield today.

Writing code got faster. Understanding what the years mean did not.

Tags: #PHP#Career
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

Related Posts

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind