PM Craft

The Freedom Trap

6 min read
PM CraftLegacy SystemsEngineering LeadershipProduct ManagementTechnical Debt
An old patch-cord switchboard, frayed cables left plugged in by hands long since departed — every fix is still there, none of them documented, all of them somebody else's problem to inherit.
An old patch-cord switchboard, frayed cables left plugged in by hands long since departed — every fix is still there, none of them documented, all of them somebody else's problem to inherit.
Article InsightsAI
Generating insights…

Inheriting a sprawling product is mostly archaeology, at least to start with. You read tickets nobody closed. Slack threads from people who don't work here any more. Comments in code referencing a "temporary fix" from four years ago. The architecture diagram, if you can find one, has more dotted lines than solid ones, and nobody can quite tell you what the dotted ones mean.

What you do next is mostly made up. There isn't a playbook because there can't be one. Every legacy system is bespoke by virtue of being legacy, and the rules that govern it tend to live in people rather than in documentation.

The case for taking legacy seriously

The case I'd make is that the difficulty of sweeping legacy work isn't in any one part of it. Plenty of greenfield problems are harder in isolation. The difficulty of inherited work comes from the way the hard parts arrive at once.

You're decoding a technical system someone else designed under constraints you don't have access to. You're stitching together teams that were never designed to work together. You're meeting commercial expectations set by people who assume the system already does things it doesn't. And you're absorbing the domain context, the years of edge cases and "oh, there's a reason for that", in real time, while shipping. There's no native visibility between any of those layers, so whoever holds the work tends to become the human integration layer, regardless of what their job title says. Product manager, delivery lead, BA, product owner, sometimes all of them at once.

That work rarely gets credit. Nobody promotes you for the year nothing fell over. The metrics that prove you stabilised a moving system are the absence of stories, and absences are notoriously hard to point at.

This is the part of the craft I think gets least airtime, and the part where experience tends to show most. Greenfield builds are the postcards. Legacy work is the actual job.

The freedom trap

Every legacy system was once a blank canvas that someone enjoyed. The original team had taste, momentum and freedom. They didn't need to coordinate with anyone, because there was no anyone to coordinate with. They built fast because the constraints hadn't arrived yet.

The trouble is what happens next. A first version gets built for a single early use case. A second customer asks for something close, but not quite the same, so a special case gets bolted on. A third customer needs a small variant of the second. Each addition feels reasonable in isolation. Almost none of them prompt the team to stop and ask the harder question: is there a more general thing we should be building here, instead of one more bespoke branch?

That moment, the one where you trade a fast bespoke fix for a slower abstraction, is the one teams routinely skip. The cost of skipping it is invisible at the time. The cost of not skipping it is right there on the sprint board. So the bespoke version ships, and another, and another, and the platform accretes into something tangled. Bespoke by default rather than by design.

Freedom Now → Legacy Later
  1. Year 1Stage 1 of 3

    Blank canvas

    Taste, momentum, freedom. No-one to coordinate with, no constraints to inherit. The team builds fast because there is nothing yet to slow them down.

  2. Year 3Stage 2 of 3

    Bespoke branches

    A second customer asks for something close but not quite the same. A third customer needs a small variant. Each addition is reasonable in isolation; almost none prompt the harder question about generalising.

  3. Year 7Stage 3 of 3

    Accreted legacy

    The platform has accreted into something tangled. Bespoke by default rather than by design. Someone else is now responsible for paying down a loan the original team took out and never recorded.

Greenfield and legacy are not opposite categories — they tend to be two points on the same timeline.

This is what I mean by the freedom trap. The freedom of an early-stage system isn't really freedom. It's a loan, taken out against a future that someone else will probably have to repay. The constraints you choose not to set become the constraints somebody later has to work around. Greenfield and legacy aren't opposite categories. They tend to be two points on the same timeline, and the gap between them is mostly a measure of how disciplined the first team was about pausing to generalise.

Ward Cunningham, who coined the metaphor in 1992, has been fairly clear since that he never meant it as licence to ship sloppy code. He meant it as a way of saying that your understanding of a problem evolves, and shipping a version that reflects today's partial understanding is fine, as long as you refactor when your understanding improves. The trap is what happens when teams take the first half of that sentence and quietly drop the second.

Working inside inherited complexity

Once you're inside an inherited system, the most useful frame I've found is a simple 2x2. On one axis: constraints you set, versus constraints you inherited. On the other: known, versus unknown.

The Inherited Complexity Matrix
Constraint you set
Constraint you inherited
Known
Known + Self-imposed

You set the constraint and you know what it does. The team owns both the decision and the visibility into it.

Normal product work

Known + Inherited

Someone else's constraint, but the code, the tickets and the team can still tell you what it does.

Tedious but tractable

Unknown
Unknown + Self-imposed

You made a call without seeing the consequence yet. The moment you trip over it, you find it.

Self-correcting

Unknown + Inherited

A dependency you don't know exists, on a system you didn't build, owned by a team that doesn't know they own it for you.

Danger zone — silent failures

The bottom-right quadrant — inherited and unknown — is where the silent failures live. The failures that never trip an alarm are the ones that take the longest to find.

The two left quadrants, the ones where you set the constraint, are mostly fine. Known and self-imposed is normal product work. Unknown and self-imposed usually shows up quickly, because you find it the moment you trip over your own decision.

The top-right is where most legacy work feels like it lives. Inherited, but at least known. You can read the code, ask the team, find the original ticket. It's tedious, but it's tractable.

The danger zone is the bottom-right: inherited and unknown. The dependency you don't know exists, on a system you didn't build, owned by a team that doesn't know they own it for you. This is where the silent failures live, where another team changes something they didn't realise you relied on, and a downstream number quietly moves before anyone notices. The failures that never trip an alarm are the ones that take the longest to find.

This is also where earns its keep. Chesterton's idea, in his 1929 essay The Thing, was that the reformer doesn't get to remove the fence in the middle of a field until they can explain why someone built it. In legacy work, the fence is everywhere. Every odd configuration, every weird permission boundary, every "we always do it this way" tends to have a reason. Most reasons are no longer current. Some absolutely are. The job is to work out which is which before you reach for the wire cutters.

There's a muscle shift here that I think a lot of us are unprepared for. Greenfield work rewards conviction. You make a call, the team builds, you learn. Legacy work rewards investigation and organisational visibility. You ask the questions that no individual team can answer because the answer lives between them. You map dependencies that aren't written down anywhere because the people who wrote them down are gone. You spend more time on org design than feature design, because the technical mess is often an organisational mess wearing a technical costume, an observation as old as , articulated in his 1968 paper on how systems mirror the teams that build them.

The training I've seen for this kind of work, on the whole, leans into the conviction muscle. The investigation muscle is the one you have to grow on the job, usually without anyone telling you that's the muscle you're meant to be growing.


None of this makes greenfield work easy. It has its own hard edges: vision under uncertainty, building a team and a market at the same time, the brutal honesty of a blank usage graph. But greenfield's hardness is mostly visible. People know it's hard because it looks hard.

Legacy's hardness is invisible by design, because the work, done well, is mostly the work of preventing things you can't show. That's the part I'd love more of us to take seriously, including the ones who, right now, are happily shipping the system that someone will inherit from them in three years.

Notable Quotes
Scroll
  • Shipping first-time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite. The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt.
    Ward CunninghamOOPSLA experience report, WyCash Portfolio Management System1992
  • The more modern type of reformer goes gaily up to it and says, 'I don't see the use of this; let us clear it away.' To which the more intelligent type of reformer will do well to answer: 'If you don't see the use of it, I certainly won't let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it.'
    G.K. ChestertonThe Thing: Why I am a Catholic1929
  • Organizations which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations.
    Melvin ConwayHow Do Committees Invent?, Datamation1968
  • To me, legacy code is simply code without tests.
    Michael FeathersAuthor, Working Effectively with Legacy Code2004
  • It's important to remember that when you start from scratch there is absolutely no reason to believe that you are going to do a better job than you did the first time. When you throw away code and start from scratch, you are throwing away all that knowledge. All those collected bug fixes. Years of programming work.
    Joel SpolskyCo-founder, Stack Overflow & Fog Creek Software2000
Related Reading
Scroll

More to read