Refactor in place
The architecture is sound; the code has simply accumulated mess. We add tests around current behaviour, then improve structure without changing what it does. Nothing visible changes for users.
Sites that load fast and convert
Custom builds and integrations
Bounded, auditable, human-approved
Being found, staying fast, staying safe
Software & Applications · Service 13
Somewhere in most established companies there is a system everyone depends on and nobody wants to touch. It works. It also cannot be changed safely, cannot be handed to a new developer, and gets a little more expensive every quarter. Modernisation is the discipline of fixing that in stages, while it keeps running.
Recognition
Legacy is not about age. Plenty of ten-year-old systems are fine. A system is legacy when changing it has become frightening — when the cost of a small change is dominated by the risk of touching anything at all.
That fear is rational. It usually comes from a real history: a developer who left without documentation, a framework that stopped receiving updates, a database schema that grew organically for eight years, or a set of business rules that exist only in code nobody has read since they were written. None of that is anyone's fault. It is simply what happens to software that succeeds for long enough.
The bus factor is one. Every change queues behind a single calendar, and that person cannot take a holiday without the business slowing down.
The host keeps warning you. Upgrading breaks the site, so it stays where it is — accumulating unpatched vulnerabilities each year.
Fixing one thing reliably breaks another, because the logic is entangled and there are no tests to catch it before your customers do.
The technology is unfashionable or obsolete. The developers who know it are expensive, retiring, or both.
Changes go straight to production because nobody ever built a safe place to try them. Every deployment is performed with held breath.
Something was configured by hand years ago and never written down. Nobody is confident it would come back up.
The platform, framework or plugin is abandoned. Security fixes are no longer coming and nobody is publishing patches.
Somebody proposed starting again, the number was enormous, and the project was shelved. Meanwhile the system got another year older.
The arithmetic of waiting
Deferring modernisation is often the right call for a year. It is rarely the right call for five. Drag the slider to see what typically changes as a system ages without investment.
The costs below are not hypothetical categories — they are the three things clients consistently report when they finally call. Development slows because every change requires archaeology first. Risk rises because unpatched software accumulates known vulnerabilities. And the eventual replacement gets more expensive, because the system has absorbed more undocumented business logic that somebody now has to rediscover.
Changes take about as long as you would expect. The team can still estimate confidently.
Dependencies are current or close to it. Patches are still being published.
The behaviour is still mostly understood and could be specified without excavation.
Directional, not a prediction — every system ages differently. The pattern is what matters: the curve is not linear, and the steepest part is usually years four to six.
Method
The pattern has a name — the strangler fig, after the plant that grows around a tree and gradually takes its place. New code is written alongside the old system, traffic is moved across one capability at a time, and the old part is removed only once nothing depends on it.
The advantage is not elegance, it is reversibility. At every point there is a working system. If a newly migrated component misbehaves, traffic goes back to the old path in minutes rather than requiring a rollback of an entire release. Business continues throughout, and value arrives continuously rather than in one terrifying weekend eighteen months from now.
It is slower on paper than a rewrite, and it is the reason these projects finish. Rewrites fail because the business keeps changing while the replacement is being built — so the new system chases a moving target and is out of date before it ships. Incremental replacement keeps up, because it is always in production.
Scroll on — the migration runs as you read.
Options
Not everything should be modernised. Part of the assessment is deciding which of these applies — including the one where the correct answer is to leave it alone.
The architecture is sound; the code has simply accumulated mess. We add tests around current behaviour, then improve structure without changing what it does. Nothing visible changes for users.
New capabilities are built outside the old system, and traffic moves across one route at a time behind a facade. The legacy code shrinks until what remains can be retired quietly.
Same behaviour, modern foundation. Often the answer for a bespoke system doing something an existing platform now does well — the value was never in the plumbing.
Stable, rarely changed, not exposed to the internet, and not blocking anything. Then the honest recommendation is documentation, backups and a contingency plan — not a project.
Safety
Modernisation goes wrong in predictable ways. These are the controls that prevent each of them, and they are in place before any existing code is touched.
Before changing anything, we write tests that capture what the system currently does — including the odd behaviour, because something probably depends on it.
Often the first deliverable, because you cannot safely modernise a system you can only test in production.
If the code is not already in Git, it goes in first. Modernisation without the ability to see what changed is guesswork.
New paths ship switched off, are enabled for a small share of traffic, and can be turned back off in seconds without a deployment.
For critical calculations, old and new run side by side and their outputs are compared on real data before the old one is retired.
What we learn about the system gets written down as we go. Often this is worth more than the code changes — it is what ends the bus-factor problem.
Questions
Occasionally, but far less often than it is proposed. Rewrites are seductive because the new system is imaginary and therefore perfect. In practice they take longer than estimated, the business keeps changing during the build, and the old system's undocumented behaviour has to be rediscovered anyway — usually by an angry customer after launch.
A full rewrite makes sense when the system is small, when the platform is genuinely dead, or when the business rules have changed so completely that preserving current behaviour has no value. In every other case, incremental replacement gets there with far less risk.
That is the whole point of the approach. Work happens alongside the running system, changes go through staging, and new paths are introduced behind switches that can be turned off instantly. The system stays live throughout.
The one thing we will ask for is a window to establish the safety net — staging, version control, backups — before touching anything. Skipping that step is what turns modernisation into an outage.
That is the normal case rather than the exception. The assessment includes reading the code, tracing the important paths, and talking to whoever uses the system daily — users usually know the behaviour better than any document would have captured.
What comes out of that is written down, and it is frequently the most valuable single deliverable, because it is what makes the system survivable when the one person who understands it is unavailable.
It is deliberately structured so you can. Work proceeds in stages that each leave the system in a better and fully working state, which means you can pause after any of them — when budget changes, when priorities shift, or simply when the pain has reduced enough.
That is a real difference from a rewrite, where stopping halfway leaves you with two incomplete systems and nothing to show.
Often, though it is a side effect rather than the goal. Old systems tend to accumulate inefficient queries and duplicated work, and those surface during the process. If performance is the primary concern, say so early — it changes which parts we prioritise.
A fixed-price piece of work with a written deliverable. We review the codebase, dependencies, hosting, data model and deployment process, then produce a plain-language report: what you have, what the real risks are, which route we recommend and roughly what each option costs.
It is yours regardless of whether you continue with us — you can take it to another developer, and some clients do.
Yes. Older PHP, legacy WordPress and Joomla builds, classic ASP-era systems, jQuery-heavy front ends, procedural codebases without frameworks. The technology matters less than whether the behaviour can be understood and pinned down before it is changed.
Often paired with
Call back
Leave a number and a good time. We will call you back to talk about what you are trying to build — no charge for the conversation.
Or call us directly +1 (647) 385-5532