The system everyone is afraid to touch is usually the one making money.
Legacy is not an insult — it means the thing worked long enough to become load-bearing. We modernize it in increments that keep it earning, rather than proposing the rewrite that ends up shelved eighteen months in.
- delivery
- 2-week increments
- starts with
- Characterization tests
- code lives in
- Your repository
Full rewrites fail for a reason that has nothing to do with engineering.
A rewrite asks a business to fund two systems, freeze feature work, and wait — sometimes for years — for parity with something that already works. Priorities shift, sponsors change, budgets tighten, and the project is cancelled with a half-finished replacement and an original system that is now two years further behind.
Incremental modernization is slower on paper and far more likely to finish. We put tests around current behaviour first, then move functionality out piece by piece behind an interface, so value lands continuously and you can stop at any boundary with something that runs.
What the practice covers
Roughly two-thirds of this work is on systems that already exist. Greenfield builds are the smaller half of the practice.
Legacy modernization
Characterization tests around current behaviour, then extraction behind a stable interface. Each increment ships independently and can be reverted independently. No big-bang cutover.
Custom development
New systems where an off-the-shelf product genuinely does not fit. We will tell you when one does — recommending a purchase over a build costs us revenue and saves you a maintenance liability.
Systems integration
Making platforms talk that were never designed to. Idempotent handlers, explicit reconciliation, and a dead-letter path someone actually monitors. Integrations fail; the question is whether you find out from a dashboard or from a customer.
API development
Versioned, documented, and designed around what consumers need rather than the shape of your database tables. Contract tests so a breaking change fails in CI instead of in production.
Data migration
Reconciliation counts on both sides, a rehearsed rollback, and a defined answer for records that do not map cleanly — agreed with the business before the run, not improvised during it.
Technical due diligence
Pre-acquisition or pre-investment assessment of a codebase, its delivery practices, and its key-person risk. Written plainly enough for an investment committee, specific enough for the engineers who inherit it.
How a software engagement runs
Tests before changes. On a system nobody fully understands, the tests are how you find out what it currently does.
Read the system, not the documentation
We work through the code, the database, and the production logs, and we talk to whoever supports it. The output is a written account of what it actually does, which routinely differs from what everyone believes.
Characterization tests
Tests that pin current behaviour — including the behaviour that looks like a bug but that something downstream depends on. This is the safety net that makes everything after it possible.
Extract in increments
Functionality moves out piece by piece behind an interface, each increment behind a flag and independently reversible. You can stop at any boundary and still be ahead.
Leave it supportable
Architecture decision records, a runbook, and pairing sessions with the team who will own it. We consider the engagement finished when your engineers can make the next change without us.
Retiring a quoting system one endpoint at a time
Drawn from engagements the founders ran at previous employers, before CloudMind existed. It is not a CloudMind client reference, and we will not present it as one.
A 14-year-old quoting application in an unsupported framework, with the original developer long gone and no test suite. It produced every customer quote in the business, and two rewrite attempts had already been abandoned.
What we did
- Characterization tests covering 240 historical quotes, including eleven cases where the legacy pricing logic was arguably wrong but downstream reports relied on it
- A routing layer in front of the application so traffic could move endpoint by endpoint
- Pricing, then catalogue, then document generation extracted across eight increments
- The legacy system kept running and serving un-migrated endpoints throughout
They found eleven places where the old system did something odd, and asked us which ones were bugs. Nobody had ever asked.
- Increments, each shippable
- 8Increments, each shippable
- Quoting outages during migration
- 0Quoting outages during migration
- Pricing quirks documented, not silently fixed
- 11Pricing quirks documented, not silently fixed
[PLACEHOLDER STAT] Figures are illustrative. Replace with real numbers from the founder’s prior engagement, cleared by that employer and with a contactable reference — or remove the section until one exists.
What people ask before they sign.
If your question is not here, ask it directly — we would rather answer it now than in month three.
Should we rewrite or modernize?
Modernize, in almost every case where the current system is in production and earning. A rewrite is defensible when the platform is genuinely unsupportable, when the domain has changed so fundamentally that the model no longer fits, or when the system is small enough to replace in weeks. Those cases are rarer than they feel from inside the frustration of maintaining something old.
What if the original developers are gone and nothing is documented?
That is the common case, and it is what the first two weeks are for. The code and the production database are the documentation. Characterization tests then let us change things safely without a complete understanding up front — you do not need to know why a behaviour exists to protect it while you work around it.
Do you work in our stack or bring your own?
Yours. Introducing a language your team cannot maintain would leave you more dependent on us, which is the wrong outcome. If we think the stack is genuinely a problem, we will say so and let you decide — but we will not solve it by quietly adding a second one.
Who owns the code?
You do, in your repository, from the first commit. No escrow arrangement, no licensed components you would have to keep paying for, and no build that only runs on our machines.
How do you estimate work on a system nobody understands?
We do not give you a fixed price for the whole thing, because anyone who does is either padding heavily or about to have a difficult conversation with you. We fix the price of the first two weeks, and by the end of it we can estimate the increments with real confidence. Each increment is then separately scoped and separately stoppable.
Start with a software consulting assessment.
Two weeks, fixed fee, no commitment to a build. You end up with a written account of what you run today and a costed plan — yours to keep even if you take it elsewhere.