Modernizing a Construction System You Cannot Turn Off
CodeBranch Team
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 over | Replace behind seams | |
|---|---|---|
| First production value | At the end | Within weeks |
| Risk profile | Concentrated on one date | Spread across many small releases |
| If the project stops early | Nothing usable | The finished pieces keep running |
| How correctness is proven | Testing before the switch | Both systems, same inputs, compared |
| Cost of an undiscovered behaviour | Found in production, after cutover | Found during parity, old system still live |
| Total effort | Lower in theory | Higher, 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?
Is old technology by itself a reason to rewrite?
Where should the first piece of a modernization be?
How do you know the replacement is correct?
What happens to the knowledge locked in an old system?
How do we evaluate a partner for a legacy modernization?
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.
Related Articles
Why Generic CRMs Break on Project-Based Construction Sales
A horizontal CRM treats the deal amount as an input. In construction it is the output of a technical design still being produced while the deal is open.
Offline-First on a Jobsite Is a Product Decision
A jobsite is a permanent network partition, not an outage. What the app can still do without a connection is decided before any sync code is written.
Connected Construction Tools Produce Readings, Not Data
Pairing a Bluetooth tool is the solved part. A reading only becomes data when the system knows what it measured, where, and for which project.