Engineering5 min read

The hardest part of a legacy system is staffing it

The code was never the problem. Finding one senior engineer willing to own an old .NET backend was, and what fixed it was the job description, not the pay.

A client arrived with a large backend on an old version of .NET. Real volume, years of accumulated business rules, no automated tests, no CI, deploys done by hand. The people who wrote it had moved on.

Everyone involved assumed the hard part would be the code. It was not. We had read worse. The hard part was that for eighteen months they had been unable to put one senior engineer in front of it who would still be there six months later.

That is the part of legacy work nobody writes about, so here it is.

The pool is smaller than the job ad assumes

Recruiting for this looks like recruiting for any backend role, and it is not. Each qualifier removes far more people than it appears to.

Four narrowing stages: developers who know C# and .NET, then those who know the older framework and its quirks, then those who will accept a role described as maintenance, then those who will still be there in a year. Describing the role as ownership with a modernisation mandate widens the third stage, and funding the safety net first while naming the end state widens the fourth.
The first two stages are a skills question. The last two are a description question, which is the only one you control this quarter.

The first narrowing is real and unavoidable. Knowing C# is not the same as knowing what a particular framework version does under load, which packages were abandoned, and why a piece of code that looks wrong is load-bearing.

The next two narrowings are not about skill at all, and they are where almost everybody loses candidates.

Why good engineers decline

Ask them and the answers are consistent. None of them are about the technology.

There is nothing to show afterwards. Two years keeping an old system running produces no portfolio, no talk, no repository anyone can look at. The engineer who does this well becomes less employable than the one who shipped something mediocre in a fashionable stack.

Nobody wants to be the only person who understands it. Being irreplaceable sounds like security until you try to take a holiday, or move team, or leave. Experienced people have been the single point of failure before and will not volunteer for it twice.

The work is unfalsifiable. If it keeps running, nobody notices. If it breaks, it is your fault. There is no version of that arrangement where the engineer wins.

Maintenance has no end state. A role with no defined finish is a role you can only leave by resigning.

What changed it

We did not solve this by paying more, although the role does pay above a comparable modern one and should. We solved it by describing a different job.

Ownership, with a mandate to change things. Not "maintain the .NET system" but "own this system and take it somewhere better". The technical plan was the same either way: stabilise, make it observable and testable, then modernise incrementally. The difference is that one of those is a description of custody and the other is a description of work.

The safety net funded before anything else. The first weeks went to CI, a reproducible build, and tests around the paths that carry money. That is not overhead. It is what turns "I am the only one who can touch this" into "anyone competent can now touch this", which is the fear that made the role unattractive in the first place.

A named end state. Which parts are moving to a supported runtime, in what order, and what "done" means for each. Even a rough version changes the conversation, because it turns an indefinite holding action into a project with a shape.

A second person, early. Not a full pair. Enough that a review has an audience, that a holiday is possible, and that the knowledge exists in two heads. The cost of the second person is far below the cost of the first one leaving.

What to select for

The instinct is to look for the framework version on a CV. In practice the version is learnable in a fortnight and the traits are not.

  • Reads code faster than they write it. Most of this job is reconstructing intent from code with no comments, no tests and no author to ask.
  • Comfortable without a safety net, temporarily. The first changes go in before the tests exist. Some people find that unbearable, which is a reasonable position and a bad fit.
  • Treats surprising code as information. The engineer who opens a file and says "this is terrible" has learned nothing. The one who asks "what was true when someone wrote this" usually finds the constraint that is still true.
  • Writes things down. In a system with no documentation, the person who leaves a trail is worth two who do not.

We would rather hire a strong engineer from an adjacent stack who has these than a specialist in the exact framework who has none of them. On this project that is exactly what happened.

Three things that do not work

Contractors alone, for a system you depend on. Fine for a defined piece of work. Not fine as the arrangement that stands between your business and an outage, because the knowledge leaves with the invoice.

A junior plus documentation. The documentation does not exist, which is the whole problem, and writing it is the senior task you were trying to avoid buying.

Rewriting instead of hiring. The cheapest way to avoid a difficult hire is to propose replacing the system, which converts a staffing problem into an eighteen-month delivery problem while the original system still needs someone. We have written about why the rewrite is the expensive answer.

Where this one got to

The system is stable, in CI, with tests around the parts that matter, and moving onto a supported runtime service by service rather than in one jump. The client's own description of the outcome is that they stopped thinking about it, which is the correct end state for infrastructure.

The engineer is still there. That was the actual deliverable, and it came from how the work was framed rather than from what was paid for it.

If you are trying to fill a role like this and it has been open for months, the problem is probably not your market. It is probably your job description, and that is a much cheaper thing to fix.