Illustrative example

Making an ageing .NET system safe to change again

An eight-year-old .NET application still ran a professional-services firm, but a one-line change took three weeks and only two people dared touch it. We modernised it incrementally — deployment and tests first — until change was cheap again, with no rewrite and no feature freeze.

Sector
Professional services
Service
Modernization
Timeframe
Assessment + 5 months incremental work
  • C# / .NET
  • ASP.NET
  • SQL Server
  • Azure DevOps
  • xUnit

This is an illustrative example

It represents the kind of engagement we take on and the shape of outcome we work toward — a composite drawn from common situations, not a specific client. The company is anonymised, and the figures are representative targets rather than measured results. Real, client-approved case studies will replace these as engagements complete.

The problem

The application worked. It also frightened everyone. Releases were manual and took the better part of a day, so changes were batched, batches were risky, and releases grew rarer and larger — the classic doom loop. Two engineers understood the whole thing; one was close to leaving. The board had been quoted a rewrite with a very large number attached.

Constraints

  • The business could not stop for a rewrite, and feature requests kept arriving.
  • The knowledge was concentrated in two people, one a flight risk.
  • Nobody could say, with evidence, where the real cost of change actually was.

What we did

We started with an assessment — the code, but also the deployment pipeline, the environments, and how work moved from idea to production. The finding was the common one: the binding constraint was not the architecture, it was the deployment. A team that cannot release confidently is slow at everything else.

So the sequence was deliberately unglamorous:

  1. Made it deployable. A repeatable build and an automated pipeline in Azure DevOps, before touching any structure.
  2. Put tests around what we were about to change. Characterisation tests that pinned existing behaviour — including the quirks — so change stopped being a gamble.
  3. Remediated versions and dependencies that blocked everything else.
  4. Introduced module boundaries inside the existing system, enforced by architecture tests in the build rather than by good intentions.

Only then did structural work become safe, and even then we strangled just the two components that genuinely needed it. The rest — stable, rarely changed — we left alone. Not everything old is debt.

Architecture

The destination was a modular monolith, not microservices. There was one team, one deployment pipeline, and no distributed-systems experience on staff — decomposing the system would have added a network in the middle of the difficulty they already had. Clear internal boundaries gave most of the benefit at none of the operational cost, and left the option to extract a module later if a real reason appeared.

// A boundary enforced in CI is worth more than any amount of documentation
// about the boundary.
[Fact]
public void Billing_does_not_reach_into_Scheduling_internals()
{
    var result = Types.InAssembly(typeof(BillingService).Assembly)
        .That().ResideInNamespace("Firm.Billing")
        .ShouldNot().HaveDependencyOn("Firm.Scheduling.Internal")
        .GetResult();

    Assert.True(result.IsSuccessful);
}

Lessons

Every phase delivered standalone value, so the programme survived a mid-course change of priorities — which is exactly the property a rewrite lacks. By the end the team could change the system without fear, and the knowledge that had lived in two heads was in tests, records and a deployment anyone could run.

Representative outcomes

11 days → 2 days

median lead time for a change

manual → automated

deployment, from a day to minutes

0

big-bang rewrite; the system stayed in production throughout

Figures are illustrative targets for an engagement of this shape, not measured results from a specific client.

More selected work

Illustrative Idea to Software

Replacing paper job sheets for a field-service company

A 120-person field-service company ran its daily work on paper job sheets that were rekeyed by hand each evening. We replaced that with a mobile-first workflow platform, cutting the rekeying entirely and getting invoices out days sooner.

Illustrative AI Adoption

An AI document-extraction pilot that had to earn its place

A finance operations team drowning in supplier invoices wanted "AI". We ran a three-week sprint that defined the accuracy bar first, built a working extraction prototype on real documents, and evaluated it honestly against that bar — with a human in the loop and a clear fallback.

Have a problem shaped like one of these?

A 30-minute call is enough to tell you whether we can help, what it would take, and what the sensible first step is. No obligation, no pitch deck.