Framework selection feels like a technical decision. It's a long-term financial commitment — and most teams make it based on GitHub stars and what the last senior hire was comfortable with.
There's a sprint you've already lost, even if you haven't named it yet. A major framework version ships. Your team stops delivering features. Two or three weeks later you're back to where you were — nothing changed for your users, but your backlog grew, your team is worn down, and a quiet resentment toward the codebase got a little louder. That sprint cost you somewhere between thirty and a hundred thousand pounds depending on your team size. And it will happen again. It already has.
This is what framework dependency looks like in practice. Not a dramatic architectural collapse — a quiet, recurring tax on every sprint, every hire, every upgrade cycle. It compounds. And because it compounds gradually, it never quite reaches the threshold where someone calls it what it is: a business risk that was priced in incorrectly, very early on.
Most teams choose frameworks the way they choose restaurants when they're tired — whatever looks popular, whatever the last senior hire is comfortable with, whatever came up at the last conference. GitHub stars, glowing blog posts, the framework someone used at their previous job. These are social signals. They are not engineering criteria. And social signals make poor foundations for systems you'll be maintaining in five years.
What you actually signed
When you adopt a framework, you are not adding a library. You are entering into an implicit long-term obligation with a third party whose incentives are not aligned with yours. You agree to track their release cadence. You agree to migrate when they break backwards compatibility — and they will. You agree to recruit from their talent pool, which means your hiring options narrow to whoever knows their way around that particular set of abstractions. You agree to inherit their architectural opinions, including the ones you'd never have chosen yourself. You agree to absorb the consequences when a lead maintainer changes jobs, loses interest, or takes the project somewhere you didn't expect.
None of this is in the README. All of it is real. The question isn't whether these costs exist — it's whether you evaluated the need against the cost before you took the dependency on.
A landlord doesn't care about your business continuity. They care about their property. When your framework maintainers ship a breaking major version, they are optimising for their own trajectory — architectural cleanliness, their view of the future, the demands of their largest contributors. Not your sprint plan.
You can't negotiate the terms. You can't defer indefinitely — security patches and ecosystem compatibility will force your hand eventually. You just pay the migration cost, absorb the disruption, and get on with it. Then you wait for the next one.
Where the costs actually hide
The visible costs of framework debt are obvious enough: the sprint lost to migration, the security patch that required days of integration work. The real damage accumulates in the costs nobody puts on a spreadsheet.
The Stepsize number is the one that should stop you. Over half your engineers have considered leaving not because of pay, not because of culture, but because of code. That's a retention crisis with a technical cause — and framework coupling is one of the primary contributors to the kind of architectural debt that makes experienced engineers feel like they're fighting the codebase every day.
What a migration sprint actually looks like
Here's how it typically unfolds in practice. This is a composite drawn from real patterns across teams we've worked with.
This isn't a story about a bad framework or a bad team. React is well-maintained and this team handled it professionally. This is just what framework major versions cost — and this was a migration that went reasonably well.
Hiring pool narrowing
Every niche or ageing framework you depend on shrinks the pool of candidates who can contribute without a lengthy ramp. You're either paying a hiring premium to find the right profile, absorbing a longer time-to-productivity cost as you train, or making compromises on candidate quality because the market for your stack is thin.
There's a secondary effect less often discussed: when your stack isn't marketable, you lose engineers to it. Experienced developers want to keep their options open. A team running an ageing framework version will haemorrhage its best people quietly and consistently.
The test surface problem
The more tightly your business logic is coupled to framework internals, the harder it becomes to test that logic without starting the whole stack. You end up with integration tests doing the work of unit tests, slow build pipelines misdiagnosed as an infrastructure problem, and feedback loops long enough that engineers start making changes without running the full suite.
The rewrite conversation
Framework lock-in rarely produces a single catastrophic failure. It produces slow degradation — an accumulation of migration debt, test friction, and architectural compromise — until someone in a planning meeting says the words: "I think we need to consider a rewrite."
That conversation is always framed as a fresh start. In practice it's one of the most expensive commitments an engineering organisation can make, and it is almost universally underestimated.
In April 2000, Joel Spolsky called Netscape's decision to rewrite their browser from scratch "the single worst strategic mistake that any software company can make." Netscape 4.0 shipped in 1997. The next major release — version 6.0, rewritten from the ground up — arrived in late 2000. Three years during which the company could not respond to Internet Explorer and watched its market share collapse. Lou Montulli, a Netscape engineer at the time, was direct: "This one decision cost Netscape three years."
The rewrite didn't fail because Netscape's engineers were poor. It failed because a functioning production system contains accumulated knowledge that cannot be fully recovered by reading the code. Every bug fix is institutional knowledge encoded in working software. When you throw the code away, you throw all of that away too.
The Netscape example is dramatic, but the physics are the same at every scale. When you choose rewrite over refactor, you are betting that rebuilding all that implicit knowledge from scratch is cheaper than working carefully with what you have. That bet almost never pays.
Before and after: the same team, two approaches
The same team. The same product type. Two different postures toward dependency. Here's what diverges over three years.
The gap they were filling has closed
There is a reasonable objection to all of this: frameworks exist because writing everything yourself is worse. That was true. It is worth being precise about why it was true, because the reason has changed underneath us.
Frameworks were compensating for missing platform capability. Front-end frameworks existed because the browser could not do components, could not scope styles, could not manage a view without a pile of jQuery holding it together. Go web frameworks existed because routing, middleware and request handling in the standard library felt like too much assembly. In both cases the framework was buying you something the platform did not have, and the coupling was a fair price for it.
That trade has moved. net/http gained routing patterns and method matching; a large and growing number of Go teams now ship production services on the standard library and reach for nothing else — we have written about why. In the browser, Web Components, Shadow DOM, CSS custom properties, native modules and container queries have filled most of the holes the framework generation was built to paper over, and the tooling required to be productive has collapsed accordingly.
So the question is no longer "framework or write it all yourself." It is whether you are still paying for a bridge over a gap that has since been filled in. Most teams have never re-asked it. They adopted under one set of platform constraints, the platform improved, and the dependency stayed — not because it was re-justified, but because nobody scheduled the conversation.
That is the same failure as everything above, one level up. The costs in this article accumulate because a decision made under specific conditions is never revisited when the conditions change. Usually the conditions are your own — headcount, users, scale. Sometimes the whole industry moves and the decision is left standing on ground that is no longer there.
A different posture
Treat your business logic as the asset, not the framework
The framework is a vehicle. Your domain logic — the rules, workflows, and decisions that make your product valuable — is what matters. Keep them cleanly separated.
Know the exit cost before you enter
Before accepting any significant dependency, spend an hour answering one question: what would it cost to replace this in two years? If you can't answer clearly, you don't understand the dependency well enough to accept it.
Prefer boring and explicit over fashionable and magical
A dependency you understand completely and that changes slowly is worth more than one that's fashionable and fast-moving. Boredom in infrastructure is a feature.
Budget for upgrade cadence as an operating cost
Put it on the spreadsheet before you ship a line of code. A dependency you can't upgrade on schedule is a dependency you eventually can't secure.
Invest in legibility as a first-class concern
The most underrated property of a production codebase is how quickly a new engineer can form a correct mental model of it. Framework magic actively destroys legibility.
The question worth asking now
"If the team maintaining our primary framework ceased to exist tomorrow — what would that cost us, and how long would recovery take?"
If you don't have a crisp answer, the dependency isn't managed — it's just unexamined. That's the gap between a technical decision and a business risk position.
Most engineering organisations cannot answer this for their web framework, their ORM, their job queue library, or their authentication provider. That's not unusual. It is a problem — because these are exactly the dependencies that open the rewrite conversation three or four years from now.
The teams that avoid that conversation aren't luckier or smarter. They applied the same scrutiny to dependency choices that a good finance team applies to vendor contracts — because that's what a framework dependency is. A vendor contract. Without the paperwork. Without the SLA. Without the exit clause.
The hidden cost of your framework choices isn't hidden at all, once you know where to look. It's in your sprint retrospectives. It's in your onboarding documentation. It's in the engineers who left. It's in the features you didn't ship last quarter. It's been accumulating for years. It just didn't have a line item.
We audit codebases, map dependency risk, and build practical plans for teams who've inherited decisions they need to understand before they can move past them.
References
- Dalal, V., Krishnakanthan, K., Münstermann, B., Patenge, R. McKinsey Digital, "Tech debt: Reclaiming tech equity" (October 2020). Survey of 50 CIOs at financial-services and technology companies with revenues over $1bn, conducted July 2020: tech debt estimated at 20–40% of the value of the entire technology estate before depreciation. mckinsey.com
- Gartner, Application Innovation & Business Summit (2025). 25% of engineering time and budget consumed managing technical debt.
- Stack Overflow Developer Survey 2024. 65,437 respondents, 185 countries. Technical debt ranked as the #1 developer frustration at work. survey.stackoverflow.co
- Stepsize, "The State of Technical Debt 2021." Survey of 200+ engineers across enterprises, SMEs and startups: 51% have left or seriously considered leaving because of technical debt. Stepsize sold technical-debt tooling at the time of publication. stepsize.com
- Joel Spolsky, "Things You Should Never Do, Part I." Joel on Software, April 2000. joelonsoftware.com
- Lou Montulli (Netscape engineer), cited in Herb Caudill, "Lessons from 6 Software Rewrite Stories," Medium, February 2019.
- Industry composite. Software maintenance accounts for 50–80% of total cost of ownership over system lifetime. Approximately $0.41 in technical debt accrues per $1 of new software development spend.