All articles
12 September 2026
9 min read

Maintenance mode: running a legacy system safely

By Tim Rutte, Cloud & Software ArchitectTopicLegacy & Modernization

A car under a cover in an empty garage, a blue charging cable running to the wall box.

Not every legacy system deserves modernizing. When the product line is winding down, the contract ends, or another platform replaces it in eighteen months, every modernization is money in a product on its way out. When that is the right conclusion is covered in its own article.

What comes after that is not covered there, and it is the part that goes wrong in practice. Because "we are not modernizing" regularly gets implemented as "we are doing nothing", and those are very different things.

This article describes what a proper maintenance mode contains: five things that keep running, three that stop, and the two pieces of information without which it is not maintenance mode but neglect with a better name.

Freezing is a decision, not a state

From the outside, a frozen system and a neglected one look the same. Neither gets new features, and in both, apparently nothing happens.

The difference lies in two pieces of information that either exist or do not.

An end date. When does the system get switched off? Without it, no decision about effort is possible: whether a measure is worth it depends on how long it will carry. The date may be rough, it may move, and it has to exist.

A name. Who is responsible until then? Not a team, a person. A system with no named owner is exactly the system where, in an emergency, three people in a row say they will take a look.

Both belong somewhere that belongs to somebody: a calendar entry, an entry in the system inventory, a note on paper for all I care. Not in a document nobody opens after writing it.

Five things that keep running

A frozen system is not a switched-off one. It sits on the network, it processes data, and so the following five things do not stop.

One: security updates for the runtime. Operating system, web server, database. That is the part most likely to be misread as "we are not changing anything any more", and it is the most important one.

Two: backups and their restoration. A backup nobody has restored is an assumption. In maintenance mode it is needed less often and matters just as much, because nobody works with the system daily any more and so a fault stays unnoticed for longer. A restore test per quarter is a defensible frequency.

Three: monitoring, reduced to what is needed. Is it up, can it reach the database, is the disk full, are the backups running. Four checks are enough. What is no longer needed are measurements for optimizations nobody will make.

Four: certificates and expiry dates. The most common outage of a frozen system is an expired certificate. Automatic renewal belongs set up even when nothing else gets touched, because otherwise that one task depends on a calendar entry that leaves the building with a person.

Five: bug fixes that affect operations. What stops the business gets fixed. What is merely ugly does not. The line is narrower than it sounds, and it only holds if somebody defends it.

Three things that stop

The opposite list matters just as much, and it is the part that needs enforcing.

New features. The core of the decision and the place where it almost always softens. The wish for "just one small change" does not stop because a system has an end date, and every granted exception makes the next one easier.

Tidying for its own sake. Refactoring, library updates with no security reason, structural improvements. All of that pays off over years, and there are no more years here.

Optimization. A frozen system running at the same load for years does not get made faster. If load rises, that is a reason to revisit the decision, not a reason for a cache.

Isolation: the system must take nothing with it

The technically most important part of maintenance mode is isolation, and it is the one most often skipped, because it is work with nothing visible to show.

The guiding question is: what happens if this system fails tomorrow? If the answer contains more than this one system, isolation is not finished.

Three directions belong checked.

What depends on it? Systems that call this one and cannot work without it. Every such connection needs either a behaviour for the failure case or decoupling through a queue. That is not a rebuild of the legacy system, it is a measure on the other side, and therefore allowed.

What does it depend on? Services this system needs. Every one of them is a failure source that has to outlive it. Third-party services on the internet play a special role: an interface being switched off brings a frozen system to a halt, and nobody reads the provider's announcements any more.

How much network does it see? Here the usual order reverses: a system without maintenance gets as little access as possible. No admin access from the internet, no outbound connections beyond the mandatory ones, and access limited to the people actually responsible.

# What does this system even talk to? Record for a week and the list of
# mandatory connections is settled.
ss -tnp | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn

# And who talks to it? The same question from the other direction.
ss -tn state established | awk '{print $4}' | cut -d: -f1 | sort -u

What can be dropped in this state is more than you would think: Removing features nobody uses any more.

Pinning dependencies down

A frozen system should not change by itself. That sounds obvious and is not: in many projects some step pulls the latest versions of dependencies at deploy time, and a restart after two years then installs something other than what was running.

Three measures prevent that, and all three are one-off work.

Pin versions, including the base image. No moving reference to a version, a fixed one. That applies to application dependencies just as much as to the operating system image.

Keep the runnable result, not just the recipe. A build that fetches packages from the internet may not work in three years because a registry was shut down. A stored image or an archive of the dependencies is the insurance against that.

Build it from scratch once before maintenance mode begins. That is the test for both points above, and the only way to demonstrate them. The build takes a day and answers the question of whether the system could come back at all after a server loss.

The rule for the changes that happen anyway

Experience says there will be changes. A legal requirement, a tax rate, a partner changing their interface. A rule forbidding that gets broken, and then there is no rule at all.

What works is a rule with a door in it:

  • Changes need an external trigger. Law, contract, security, outage. A wish from inside the company does not count, however small.
  • No change extends the end date. That is the most important of the four. Otherwise maintenance mode becomes a permanent state under another name.
  • Every change is built on the same base as what is running. No new library version, no new language version, just to make this one change.
  • One person decides. The one from the first section. No committee, no vote, or the decision takes longer than the change.

Whether leaving this state pays off is a calculation of its own: The business case for a modernization.

The exit: date and trigger

Maintenance mode ends in one of two ways, and both belong described beforehand.

At the date. The system gets switched off, the data moves into an archive. That is the planned route, and it needs its own lead time: who still accesses it, which data has to be retained, in what form it stays readable. An export into a format somebody can still open in ten years serves a retention obligation better than a server nobody can start in ten years.

At a trigger. Something happens that invalidates the decision, and then it gets taken again rather than carried forward. Four triggers are worth writing down in advance: the replacement slips by more than six months. Usage rises instead of falling. A vulnerability can no longer be closed because the version has fallen out of support. The responsible person leaves.

The third one happens most often and is treated as a trigger least often. A component reaches its end of life, and then three options are open: switch off earlier, isolate and accept the risk in writing, or modernize after all. Carrying on as before is none of them, even though it feels like one.

How to tell it is no longer one

Finally, the check worth running a year later. Four questions, and every no means maintenance mode has turned into neglect.

  • Can anybody state the end date without looking it up? If nobody in the room can name it, it no longer exists.
  • When was a backup last restored? There is an answer with a date on it, or there is not.
  • When did the runtime last get updated? More than six months is a finding.
  • Who is responsible, and do they know it? The second half of the question is the important one.

A system in maintenance mode is a deliberately accepted risk with an end. One in neglect is an unknown risk with no end, and the difference costs nothing beyond attention at four points in the year.

And if the check shows the decision no longer holds: how a step-by-step modernization works is on its own page. After a proper maintenance mode it is cheaper than before, incidentally, because isolation and dependencies are already settled.

This article belongs to a series about systems that already exist. The retrospective orders every article in it by situation.