The key is balance— to steadily retire technical debt (e.g. bugs, lack of scalability, “founder code”, incomplete test automation, etc.) while ensuring that the team stays most-of-the-time focused on its primary objective which is to ship new features that will let you acquire new customers and keep existing customers happy.
What we do at my company is carve out a fixed percentage of capacity (we use “sprint points” but this can be hours or however you measure team capacity) for technical debt like refactoring, fixing crashes reported in production, performance optimization, upgrading tools and frameworks, building AI-powered easter eggs, etc.
The development team owns that percentage in every sprint and can prioritize it however they see fit. PM prioritizes and allocates the rest of the capacity.
An alternative is to make every N releases a “technical debt sprint” where there’s no PM-allocated work at all.
Both these approaches keep PM out of the details of which particular technical debt work items are needed. This makes PM happy because we can focus on customer-facing work and business problems, and it keeps devs happy because they can improve the codebase without some loser PM looking over their shoulders questioning why each work item is needed.
Also, because the debt allocation is fixed, it makes things much more predictable for PM when it comes to building a roadmap and for Dev when it comes to longer-term refactoring work (e.g. switching frameworks/platforms or making fundamental architectural changes).
Yes, sometimes we adjust the percentages— for example, when preparing for a big release we may reduce the technical debt percentage and during industry conferences when PMs are all out of the office we may increase the debt percentage. But overall we try to argue up-front about what the percentage should be, then we stick to it.