If you’ve worked in software for any length of time, you’ve probably had some version of this conversation:
“We know this isn’t how we’d build it now, but it’s what we had to do at the time.”
That’s technical debt in a sentence. Past decisions that made sense in context — deadlines, unknowns, constraints — are now limiting what the system can do.
The same thing happens in us.
We build emotional and behavioral “code” in earlier seasons of life that helped us survive, belong, or stay safe. Years later, that old code is still running quietly in the background, shaping what feels possible.
Technical debt, briefly
Classic technical debt isn’t just “bad code.” It’s code that was once the best we could do given:
- The information we had
- The time we were given
- The tools and skills available
Over time, the context changes. The product grows, the team changes, the architecture evolves. What once felt fine now feels like a constraint. We notice it when:
- Small changes take huge effort
- We’re afraid to touch certain parts of the code
- New features twist awkwardly around old assumptions
Debt isn’t a moral failing.
It’s a byproduct of building real systems under real constraints.
Our personal “legacy code”
In coaching, I often hear people describe themselves in a way that sounds a lot like a technical debt conversation:
- “I know I say yes to too much, but it’s just who I am.”
- “I always end up smoothing things over.”
- “I can’t seem to ask for what I need without feeling guilty.”
When we look closer, those patterns usually made sense at an earlier point in life:
- Saying yes kept you safe in a family or workplace where “no” wasn’t an option.
- Smoothing things over was how you maintained connection in a home full of conflict.
- Staying quiet about your needs helped you avoid being labeled “too much.”
These strategies were intelligent responses to real constraints.
They often kept you connected, employed, or out of trouble.
The trouble is that life changed — but the old code kept running.
When old strategies become debt
Technical debt becomes painful when it collides with the present system’s needs. The same is true of our inner patterns.
Some examples I see often:
- The over-responsible engineer. Growing up, they had to anticipate everyone else’s needs. Now they quietly absorb every dropped ball and burn out.
- The conflict-avoidant manager. As a kid, conflict meant instability. Now they delay hard conversations until the team is silently boiling.
- The chronic shape-shifter. Adapting to others’ expectations was once a survival skill. Now it makes it hard to know what they actually want from their career.
In each case, the old pattern is still trying to protect something — belonging, safety, stability — even when the context has changed.
Refactoring vs. rewriting yourself
When people first notice these patterns, they often swing to the other extreme:
“I have to stop doing this. I should be totally different by now.”
That’s the equivalent of deciding to rewrite a legacy system from scratch. It sounds clean and decisive… until you realize how much is built on top of it.
In code, we usually know better.
We refactor in small steps:
- Write tests (or at least observe current behavior)
- Make one change at a time
- Keep the system running as we go
You can approach your own patterns the same way.
Some refactoring moves for humans
1. Get curious instead of furious
Instead of jumping straight to self-judgment (“Why am I like this?”), ask:
“When did this pattern first make sense?”
Understanding creates movement. Shame freezes it.
2. Notice where the pattern still sort of works
Most patterns aren’t 100% bad.
- Over-responsibility can come with deep reliability.
- Conflict avoidance can come with real sensitivity.
- Shape-shifting can come with real empathy.
Refactoring is about preserving what serves you while updating what doesn’t.
3. Design small experiments
Big resolutions (“I will always say no when I mean no”) collapse under real life.
Try experiments instead:
- “This week I’ll practice naming one boundary out loud.”
- “In our next 1:1, I’ll name one thing I’m noticing.”
- “Before automatically saying yes, I’ll pause and check my capacity.”
The goal isn’t to transform overnight.
It’s to gather data about what happens when you show up 2% differently.
4. Update the system around you
Changing yourself in isolation is like refactoring one function while the rest of the system assumes the old behavior.
If you begin acting differently — naming tension, setting boundaries, asking for support — the surrounding system will react.
That might mean:
- Re-negotiating expectations
- Clarifying roles
- Changing how work lands on your plate
Personal refactors stick more easily when the systems around you adjust too.
Being gentle with your legacy code
One of the most powerful shifts I see in coaching is when someone moves from:
“I’m broken” → “I make sense.”
Not because every outcome was ideal, but because their patterns were understandable given what they lived.
From there, growth stops being a verdict on your worth and becomes a design problem:
“Given who I am and what I’ve lived through, how do I want to work with this now?”
Your past isn’t something to delete.
It’s something to understand, honor, and — when it starts limiting you — refactor thoughtfully.
If parts of your “legacy code” feel like debt in your current season, you don’t have to overhaul everything at once.
You can start with one small, kind experiment.
And if you want support designing those experiments,
reach out — I’d be glad to explore it with you.