The Repair Café Mindset: Keeping Legacy Systems Alive Without the Grand Rewrite
There is a church hall in most British towns where, one Saturday a month, a handful of volunteers sit behind trestle tables with a soldering iron and a mug of tea. Someone brings in a kettle that no longer boils. Someone else brings a lamp, a radio, a bicycle brake calliper. The volunteers do not throw anything away on principle. They open it up, work out what is actually broken, and fix that one thing.
It is a decent model for legacy software, and an even better one for the conversation around it.
The kettle, the toaster and the fifteen-year-old monolith
Every engineering organisation I have worked around has a system like the kettle. It is old, it is unglamorous, it occasionally trips a breaker, and it is load-bearing for something nobody wants to talk about. Proposals to replace it have been circulating for years, each one larger than the last.
Meanwhile the repair café question never gets asked: what exactly is broken?
That is not a rhetorical flourish. In a composite drawn from several UK teams — a Leeds logistics operator with a decade-old dispatch system, a Bristol payments outfit running a pricing engine written before its founders met, a Scottish public-sector supplier with a case management tool that outlived two framework agreements — the pattern repeats. The rewrite is proposed as a single, enormous fix for a set of problems that have never been individually named.
The repair café answer is less dramatic and far more effective. Open the box. Find the fault. Fix the fault. Put it back together. Then do it again next month.
Understand before you replace
Legacy systems are usually badly understood rather than badly written. The code encodes rules nobody documented because everybody knew them at the time — a tariff band, an edge case in a fulfilment route, a statutory deadline that changed in 2014 and was patched in by hand.
Characterisation tests are the repair manual. Not tests that assert what the system should do, but tests that record what it currently does, quirks included. Write them against the boundary of the module you are about to touch, capture the current output for a representative set of inputs, and commit them. Now you have a tripwire. Now you can change something and find out within seconds whether you broke the tariff band.
It feels strange at first, enshrining behaviour that may well be a bug. Do it anyway. You can note the oddity in a comment and fix it deliberately later. The point is that the decision becomes explicit rather than collateral damage.
Seams: finding where the screwdriver goes
Michael Feathers' notion of a seam is still the most useful tool in the box. A seam is a place where you can change behaviour without editing the code around it — a dependency injection point, a virtual method, a wrapper you can slip around a call to the outside world.
The craft is in finding them cheaply. Look for the places where the code touches something external: a database, a clock, a payment provider, a file share. Those are almost always where you can introduce a seam with the least ceremony. Introduce one, wrap it, add a test double, move on.
Two or three seams in a module usually unlock enough testability to make the next change safe. You are not refactoring the world. You are loosening a bolt.
The strangler fig, done patiently
Strangler fig gets talked about as though it means building a parallel system. Usually it means something smaller: route a single endpoint, a single report, a single background job through new code, and leave the rest where it is. Old and new coexist. Traffic decides which wins.
What makes this work in practice is picking slices that are genuinely independent. In the composite logistics case, the first slice was label generation — narrow, well-bounded, with a clear correctness test in the form of a printed label a warehouse operative can check. Nobody needed to agree on an architecture. They needed to agree on one endpoint.
Six months of slices later, the monolith was doing considerably less, and nobody had asked for a freeze on feature work.
Repair evenings
Here is the part most modernisation plans leave out: the volunteers.
A monthly repair evening — two hours, no agenda, anyone welcome to bring a piece of the codebase they do not understand — does three things at once. It spreads knowledge that currently lives in one person's head. It surfaces small fixes that never make it into a sprint. And it gives newer engineers permission to be curious about the oldest parts of the system, which is where the risk actually sits.
Keep it low-ceremony. A shared document listing the parts of the system nobody has opened. A rota so the same three people are not always the ones holding the soldering iron. Occasionally, cake.
The cultural effect is disproportionate. When a codebase is treated as repairable rather than doomed, people stop avoiding it.
What good looks like a year in
Not a shiny new platform. More likely: characterisation tests around the three most dangerous modules, two seams introduced where there were none, one endpoint and one nightly job served by new code, a deprecation list that is actually shrinking, and a person on the team who can explain the pricing rules without opening the file.
That is the repair café outcome. The kettle still boils. Nobody had to buy a new one. And the person who fixed it now knows how it works — which, if you think about it, was always the point.