Skip to content
Legacy Rescue

Taking over software nobody understands

How to get a grip on an undocumented system safely: what to read first, what to change first, and why the ugly parts are usually load-bearing.

4 min read
Taking over software nobody understands. An article by Athabasca Solutions.

There is a specific kind of software that keeps a business running and that nobody currently employed can explain. It works. It has worked for years. Nobody dares touch it, and every request that involves it gets quietly declined.

Getting a grip on something like that is a real discipline, and the order is counterintuitive: you learn the most by changing the least.

Read the database first, not the code

The schema is the honest account of what the software is for. Table names, columns, and which of them actually contain data tell you what the business does in a way the code does not, because code accumulates dead paths and the database mostly does not.

Look for which tables are written to recently, which columns are entirely empty, and which relationships the database actually enforces versus the ones held together by hope. That last distinction is where most inherited bugs live, and it is covered in cleaning up a neglected database.

Then read the deploy path

Before any code, find out how a change reaches production. Not how it should. How it does.

This tells you whether you can safely change anything at all. A repository with a pipeline means you can experiment. Files copied by hand onto a server, with the live version differing from what is in source control, means your first project is fixing that, and nothing else should start until it is done.

Check whether the deployed code matches the repository. It surprisingly often does not, and the difference is somebody’s undocumented emergency fix from three years ago that is now load-bearing.

Make the smallest possible first change

Not a feature. Something trivial and visible: a label, a footer year. Push it through the entire path from your machine to production.

The goal is not the change. It is proving the path works, discovering what breaks, and finding out how long it takes. That single exercise usually turns up more than a week of reading, and it is cheap to get wrong.

Assume every strange thing is load-bearing

The condition in the middle of the invoice function that seems to make no sense is either a bug or a business rule, and you cannot tell by reading it. Six years ago a customer had a problem and somebody solved it in fifteen lines and told nobody.

So the rule is: do not remove anything you do not understand. Rename it, comment it, log when it fires, and find out. Deleting it is how a rescue becomes an incident.

Logging is the cheapest instrument here. Add a line where you are unsure, deploy it, and wait a fortnight. If it never fires, you have learned something safely. If it fires every day, you have learned something more important.

Write things down as you go

Not documentation in the formal sense. A running file of what you have worked out: what this table is for, why that job runs at 3am, what breaks if the mapping service is down.

Two reasons. It is how you build understanding rather than a collection of facts. And it is the thing whose absence created this situation in the first place.

What to fix first, once you can

In this order, because each one makes the next one safer:

  1. A way to run it somewhere other than production. Everything else depends on this.
  2. Backups that restore, tested. If the system is fragile, this is your insurance while you learn it.
  3. Anything unsupported and internet-facing. Old software that accepts requests is the sharpest real risk.
  4. Monitoring, so you find out about failures from a computer rather than a customer.
  5. Only then, the code. And even then, only the parts that a real business need is pushing against.

Everything above the code is what actually reduces risk. Refactoring first feels productive and moves nothing.

When to stop and reconsider

If, after a few weeks, you cannot run it locally, cannot find the source of what is deployed, and cannot trace what the data means, the honest conclusion is that this is not a takeover, it is a rewrite, and it should be scoped as one with the existing system left running until the replacement genuinely works.

That is a real outcome and it is better reached deliberately at week three than discovered at month eight. An independent audit is the usual way to make that call with evidence rather than instinct.

If you have a system like this and want someone to take the first pass at it, tell us what it does and what nobody dares change.

Related: what a code audit tells you, when the developer disappeared, and our legacy rescue work.

Further reading

Sections covered in Taking over software nobody understands: Read the database first, not the code, Then read the deploy path, Make the smallest possible first change, Assume every strange thing is load-bearing, Write things down as you go, What to fix first, once you can, When to stop and reconsider
The shape of the argument, in order.

Get new articles by email

One email when something new goes up, roughly twice a month. Plain writing on what software costs and what is worth building. No sequences, no sales calls, and one click to leave.

We use it for the newsletter and nothing else. Unsubscribe any time.

Have something you need built?

Tell us what the problem is. You will get an honest read on whether it is worth building, what it would take, and roughly what it would cost. No pitch deck, no pressure.

Replies within one business day. Mon to Fri, 9am to 5pm MT.

Call Start a project