Skip to content
Construction

Modernizing a Construction System You Cannot Turn Off

CT

CodeBranch Team

Modernizing a Construction System You Cannot Turn Off

The system you most want to replace is usually the one you cannot stop. It issues the invoices, it holds fifteen years of job history, and the two people who understand it are busy. That constraint is not an obstacle to the modernization plan — it is the plan. Once you accept that the old system keeps running while the new one arrives, almost every other decision follows, starting with the fact that there is no cutover date.

Quick Summary

  • A system that bills is load-bearing on cash. A cutover date is a bet on one specific day going perfectly.
  • Age is not the problem. Being unable to change the system safely, or losing the people who can, is the problem.
  • The first slice should be read-only, so the team gets a real deployment without risking a write path.
  • Correctness is proven by parity: both systems, same inputs, compared over a full business cycle.
  • The behaviour of the old system is the specification, and it has to be captured as tests before it is rewritten.

This is the other half of the question in what construction companies build when their platform runs out. Sometimes the gap is a system you never had. More often it is one you already have, that works, and that nobody dares touch.

Why Does a Rewrite With a Cutover Date Fail Here?

Because the thing being replaced is attached to money moving.

A construction back office has a rhythm: progress is recorded, a report is produced, an invoice goes out, cash arrives. A system in that chain cannot be unavailable on the day the cycle runs, and a big-bang replacement concentrates all of its risk on exactly one such day. If anything is wrong, the options are to roll back a migration that has already written new data, or to bill late.

There is a second failure that shows up earlier and is less dramatic. A rewrite is a long project with no deliverable until the end, and construction companies rarely get an uninterrupted year. Priorities move, a project goes sideways, the budget is needed elsewhere — and the rewrite is abandoned at eighty per cent, which produces nothing at all. The incremental approach fails better: stopping halfway still leaves the pieces that were finished running in production.

The alternative pattern has a name. Martin Fowler’s description of the strangler fig application is the clearest statement of it: new functionality grows around the edges of the old system, intercepting what it can, until the old system is doing little enough that it can be retired quietly.

What Does an Old System Actually Cost You?

Not what most people assume, which is why the assessment matters more than the age.

The clearest public evidence on this comes from government rather than construction. A 2019 GAO review of federal legacy systems looked at the ten most critical systems identified across ten agencies and found them to be between 8 and 51 years old. The finding worth borrowing was not the ages. It was that three of the ten agencies had no documented modernization plan at all, and only two had plans containing milestones, a description of the work and a disposal plan for the old system.

That is the real pattern. The cost of an old system is rarely the technology itself. It is:

  • Change latency. A modification that should take a day takes three weeks because nobody is confident about what it will break.
  • Key-person concentration. One or two people can safely touch it, and the company’s risk is their calendar.
  • Integration refusal. The system cannot talk to anything new, so every new tool creates manual re-entry around it.
  • Security exposure. A runtime or database version that no longer receives patches is a decision whether anyone has made it or not.

CodeBranch spent two years with two senior developers on a construction accounting and invoicing platform built in Perl and PostgreSQL. The work was not a rewrite — it was maintenance and evolution of a system the company depended on, which is the context where these four costs stop being abstract and become schedule items.

Where Should the First Seam Be?

Somewhere read-only, where being wrong is cheap.

Reporting is almost always the right first slice. The new system reads the same data, produces the same output, and nobody’s invoice is at risk if it is wrong on day one. It gives the team a real production deployment, a real user, and — crucially — a direct comparison against the existing output.

After reporting, the sequence usually runs: a self-contained write path with few dependencies, then a module with heavy integration, then the core. The ordering principle is to take the pieces where the seam is clean before the pieces where the seam has to be invented.

What makes a seam clean is worth naming explicitly, because teams often cut in the wrong place:

  • The boundary already exists in the data, not just in the code. Another module reads this through a table or an interface rather than reaching into its internals.
  • The piece can be wrong without corrupting anything upstream.
  • There is a way to compare old and new output without a human reading both.

A module that fails those three is not the first thing to move, however much the team dislikes it.

The same logic applies when a system is grown rather than replaced. The budget control platform CodeBranch built for an electrical contractor started as one idea with a modest budget and expanded module by module, driven by what the operation needed next rather than by a roadmap written in advance. A modernization is that process pointed at an existing system instead of an empty one.

How Do You Prove the New Path Is Right?

With parity, run for a full cycle, before anything is switched off.

Rewrite and cut overReplace behind seams
First production valueAt the endWithin weeks
Risk profileConcentrated on one dateSpread across many small releases
If the project stops earlyNothing usableThe finished pieces keep running
How correctness is provenTesting before the switchBoth systems, same inputs, compared
Cost of an undiscovered behaviourFound in production, after cutoverFound during parity, old system still live
Total effortLower in theoryHigher, because both run for a while

The last row is the honest cost. Running two systems in parallel is more work than running one, and the organization pays for that overlap in both money and attention. What it buys is that nobody has to be certain in advance — differences surface as data rather than as incidents.

Parity has to be measured over a complete business cycle, not a sample. In construction that means a full billing period, because the behaviours that differ are usually the ones that only occur at month end: a retention calculation, a partial progress claim, a credit note against a prior period.

What Happens to the Knowledge Inside the Old System?

It gets captured as tests, or it gets lost.

Every long-lived system contains decisions nobody remembers making: a rounding rule, a special case for one client, an exception that exists because of an audit in 2014. None of this is in the documentation. Some of it is not in anyone’s memory either — it is only in the code and in the outputs it has been producing correctly for a decade.

The method that works is to write tests against the existing system before replacing it. Feed it known inputs, record what it does, and treat that as the specification. This inverts the usual order: instead of documenting intent and building to it, you capture behaviour and then decide, case by case, which behaviours were intentional and which were bugs that the business has since built around.

That decision is not a developer’s to make alone. A rounding difference of a few cents per line is a defect to one person and a two-decade billing convention to another, and the only way to settle it is to show the difference to someone who owns the number. CodeBranch surfaces these as explicit decisions during the parity period rather than resolving them in code, because each one is a business rule being re-adopted, not a bug being fixed.

When Should You Leave It Alone?

When nothing the business wants to do next is blocked by it.

A system that is old, unglamorous, understood by someone still employed, and not in the way of anything is not technical debt. It is a paid-off asset. Replacing it consumes budget and attention that could go toward something that changes how the company operates, and the result at the end is the same capability it already had.

The test is forward-looking rather than technical. What is the business trying to do in the next two years — add a line of work, open a region, connect to a client’s system, support a field crew that does not exist yet — and does this system prevent it? If the answer is no, the right decision is to keep it patched and leave it alone.

When the answer is yes, the sequencing matters more than the technology choice, which is the same reason the cost code structure comes first in a system that is being built rather than replaced. CodeBranch treats that ordering as the first deliverable when scoping software for construction companies — and when the honest answer is that the old system should stay, that conclusion is available too.

Frequently Asked Questions

How do you modernize software that the business runs on every day?
By replacing it in pieces, with the old and the new running at the same time, rather than by setting a cutover date. Each piece is moved behind a seam the rest of the system already uses, and it is only considered done once the new path has produced the same results as the old one for a full business cycle. CodeBranch works this way on systems that cannot be paused, because the alternative asks a company to bet its billing on a single weekend.
Is old technology by itself a reason to rewrite?
No, and treating it as one is how modernization budgets get spent without anything improving. Age matters when it blocks something the business needs — a change nobody can make safely, a platform that no longer receives security updates, or knowledge held by one or two people. CodeBranch assesses the system against what the business is actually trying to do next, because a stable system nobody needs to change is not technical debt.
Where should the first piece of a modernization be?
Usually somewhere read-only. Reporting and analytics can be rebuilt against the same data without risking a write path, which gives the team a real deployment, real users and a real comparison against the old output before anything irreversible happens. CodeBranch sequences this deliberately, since the first slice is as much about proving the approach to the organization as it is about the code.
How do you know the replacement is correct?
By running both systems against the same inputs and comparing outputs over a complete cycle — a full month of invoices, a full set of progress reports — rather than by testing and hoping. Differences are either defects in the new path or undocumented behaviour in the old one, and both need a decision. CodeBranch treats that parity period as part of the work rather than as an optional validation phase.
What happens to the knowledge locked in an old system?
It has to be converted into something executable, because documentation written during a rewrite describes what people believe the system does, not what it does. The reliable method is to capture current behaviour as tests against the existing system first, so the specification is produced by the software rather than by memory. CodeBranch maintained and evolved a construction accounting platform written in Perl for two years, and that kind of engagement is where the real behaviour becomes visible.
How do we evaluate a partner for a legacy modernization?
Ask what they would do in the first ninety days, and listen for whether the answer involves running anything in production. A partner who proposes a discovery phase ending in a rewrite plan has not accepted the constraint; one who proposes a small slice live alongside the old system has. CodeBranch starts with a Product Definition phase that sequences the replacement, because on a system that cannot be turned off, the order of the work is the plan.
CT

CodeBranch Team

CodeBranch is an agentic software development partner for U.S. companies, from building new products to scaling existing ones — senior-led teams in Colombia, working U.S. hours. We deliver with AI-native pipelines and our own Spec-Driven Development framework, with quality and security built into every line of code.

LinkedIn · codebranch.co

construction legacy systems modernization custom software

Related Articles