Technical Debt Management and Refactoring Questions
Identifying, prioritizing, and paying down technical debt sustainably. Covers recognizing debt, making the case to invest in it, refactoring safely behind tests, and balancing debt reduction against feature velocity. Includes keeping a codebase maintainable over the long term.
How would you budget sprint capacity for technical debt work? Describe three practical approaches, discuss the pros and cons of each, and give an example allocation for a two-week sprint on a four-person team.
Sample Answer
Direct answer
Three practical approaches: dedicated debt sprints (a full sprint periodically focused only on debt), reserving a fixed percentage of every sprint, and embedding debt tickets directly into the feature backlog to be prioritized alongside everything else. For a small team, a percentage reservation combined with embedding is usually most practical, since a full dedicated sprint is a bigger commitment than most small teams can protect from deadline pressure.
Structured elaboration
| Approach | Pros | Cons |
|---|---|---|
| Dedicated debt sprints | Enables larger, more structural work; clear, visible commitment | Debt accumulates unmanaged between sprints; easiest for leadership to cancel under pressure |
| Fixed percentage per sprint | Steady, predictable; smaller commitment, easier to protect | Wastes capacity in sprints with little ready debt work; too small a unit for big structural items |
| Embedded in feature backlog | No separate process to maintain; naturally prioritized against everything else | Debt items reliably lose the prioritization fight against features unless explicitly protected |
Worked example
For a 4-person team on a 2-week sprint (roughly 8 person-weeks of capacity), reserving 15% for debt work is about 1.2 person-weeks: 1.2 divided by the 2-week sprint is 60% of one person's sprint, or roughly 6 of the sprint's 10 working days if concentrated in a single engineer (in practice it is usually healthier spread across 2-3 people at 2-3 days each, so no one is pulled fully off feature work). A concrete allocation: pick the top 1-2 items from the register by impact/effort each sprint, assign one engineer (rotating across the team so it's not always the same person), and timebox it explicitly on the sprint board so it's visible alongside feature work rather than treated as "whatever's left over."
Trade-offs & pitfalls
The most common failure at small-team scale is the percentage allocation quietly evaporating the first time a deadline gets tight, since a small team has less slack to absorb the loss than a larger org does; protecting the allocation requires it to be visible on the sprint board (not a private commitment) so its erosion is a team-visible trade-off, not a silent one.
Identify the common sources of technical debt in a software organization. For each source, give a practical indicator or metric you would monitor to detect it early, and a simple detection method you could run against an existing codebase.
Sample Answer
Direct answer
Technical debt in a real organization comes from six recurring sources: rushed delivery under deadline pressure, deferred upgrades, missing tests, duplicated solutions, knowledge loss from turnover, and shortcuts taken without a repayment plan. Each has its own early-warning signal, so detecting them requires more than one metric.
Structured elaboration
| Source | Early indicator | Detection method |
|---|---|---|
| Rushed delivery | Spike in hotfixes shortly after a release | Correlate deploy dates with incident timestamps |
| Deferred upgrades | Dependencies several major versions behind | Automated dependency-audit scan (e.g. npm outdated, pip list --outdated) run on a schedule |
| Missing tests | Coverage trending down on recently-changed files | Coverage-delta check per PR, not just a global number |
| Duplicated solutions | The same logic appears with small variations across files/services | Static duplication detection (e.g. jscpd, PMD CPD) |
| Knowledge loss | One person authors the majority of commits to a module, then leaves | Git blame / commit-author concentration analysis per module |
| Undisciplined shortcuts | "TODO" / "FIXME" / "HACK" comment density rising | Grep-based comment audit, tracked over time |
Worked example
A quarterly audit of a mid-size codebase finds: 40 unresolved TODO/FIXME comments concentrated in the billing module (undisciplined-shortcut signal), the billing module's primary contributor left the company two months prior with no documented handoff (knowledge-loss signal), and npm outdated shows the payment SDK is three major versions behind (deferred-upgrade signal). All three point at the same module, which is exactly the kind of correlated signal that should escalate a module from "routine backlog item" to "priority review," even though no single metric alone would have triggered that.
Trade-offs & pitfalls
A single detection method catches only its own blind spot: static duplication detection misses semantically duplicated logic written differently, and commit-author concentration can flag a module that's simply owned by a specialist by design, not one that's actually at knowledge risk. Combine at least two independent signals before escalating a module, rather than acting on any single metric in isolation.
You are planning a data model refactor that touches customer records and carries a risk of data loss or inconsistency. Design a risk analysis and mitigation plan, including testing approaches such as canaries and shadow writes, reconciliation checks, backup strategy, a rollback plan, and how you would communicate the risk to stakeholders during the migration.
Sample Answer
Direct answer
A data model refactor touching customer records needs a risk plan built around never trusting a single write path during the transition: use shadow writes or dual writes to validate the new schema against real traffic before cutting reads over, reconcile continuously rather than only at the end, and keep a tested rollback path available at every stage.
Structured elaboration
- Testing approach: shadow writes first (write to both old and new schema, but only read from and serve the old one), comparing outputs to catch discrepancies with zero customer-facing risk; only after a clean shadow-write period, consider a canary of real reads against the new schema for a small internal or low-risk user segment.
- Reconciliation checks: an automated job comparing old and new schema data continuously during the dual-write period, alerting on any divergence immediately rather than discovering it only at final cutover, since a divergence caught early is a bug to fix, while one discovered at cutover is a potential data-loss incident.
- Backup strategy: a verified, tested-restorable backup of the pre-migration state taken immediately before any schema change begins, not assumed to exist from routine backup processes that may not have been validated against this specific scenario.
- Rollback plan: since this is dual-write, rollback at any point before full cutover is just "stop reading from the new schema and continue serving from old," cheap and low-risk; define explicitly how far into the process rollback remains cheap versus when it becomes genuinely costly (typically once the OLD schema stops being written to, which should be the very last step, done only after full confidence).
- Stakeholder communication: a clear timeline shared with stakeholders showing each stage (shadow write start, reconciliation period, canary read, full cutover, old-schema decommission) so nobody is surprised by the pace, and a clear escalation path if reconciliation ever shows a divergence.
Worked example
Week 1-2: dual writes begin (new schema populated alongside old, old schema remains source of truth for reads); automated reconciliation runs hourly, comparing a sample of records. Week 3: reconciliation shows a 0.02% divergence rate, traced to a timezone-handling difference between old and new write paths, fixed and re-verified before proceeding (not glossed over as "close enough"). Week 4: canary read migration for 1% of traffic (internal tooling users first), verified for a week with no customer impact. Week 5-6: gradual read migration to 100%, keeping dual writes active as an active rollback path. Week 7-8: two full weeks of 100% reads from the new schema with zero incidents, the soak period before committing to cutover. Week 9: old-schema writes finally stop, the point of no easy return, executed last and deliberately.
Trade-offs & pitfalls
The single most dangerous mistake in this kind of migration is treating reconciliation as a one-time final check rather than a continuous, running safeguard throughout the transition; a divergence caught on day 3 of dual-writes is a minor bug fix, the same divergence undiscovered until final cutover on week 9 is a customer-data incident.
Design hiring and onboarding guardrails to reduce the likelihood that new hires introduce systematic technical debt. Include interview signals, onboarding checklists, probation goals, and early-review milestones.
Sample Answer
Direct answer
Reduce the chance new hires introduce systematic debt with guardrails at three points: interview signals that screen for the relevant judgment, onboarding checklists that transmit team-specific standards explicitly rather than assuming osmosis, and structured probation goals with early-review milestones that catch drift before it compounds into a pattern.
Structured elaboration
- Interview signals: include a code-review exercise (reviewing a deliberately flawed sample PR) specifically to assess whether a candidate notices maintainability and design issues, not just whether their own code works, since debt often comes from what a candidate DOESN'T flag as a concern, not from what they write themselves.
- Onboarding checklist: an explicit, written list of the team's standards (code-review expectations, testing conventions, architectural boundaries) reviewed with every new hire in their first week, rather than left to be absorbed informally over months, since informal absorption is exactly how inconsistent standards perpetuate.
- Probation goals: specific, checkable goals tied to the team's actual standards ("PRs consistently include appropriate test coverage by week 6," not just "contributes code"), so debt-relevant behavior is an explicit part of the ramp-up evaluation, not an afterthought.
- Early-review milestones: a structured check-in at 30/60/90 days specifically reviewing a sample of the new hire's PRs against the team's standards, catching a pattern (consistently thin tests, consistently skipping a specific review step) while it's still a habit forming, rather than after a year when it's become the new hire's established way of working.
Worked example
A 30-day review for a new hire finds a pattern: PRs consistently pass CI but their tests only cover the happy path, missing edge cases the team's standard explicitly calls for. Caught this early, it's a straightforward coaching conversation with a clear, concrete example set; caught at month 9 instead, it's an ingrained habit affecting a much larger volume of shipped code, and unwinding it (both the habit and the accumulated thin-test debt already shipped) is a much bigger undertaking.
Trade-offs & pitfalls
The risk in over-indexing on these guardrails is making onboarding feel like surveillance rather than support; frame the early-review milestones as coaching checkpoints benefiting the new hire's own growth ("here's specific, actionable feedback early, while it's cheap to adjust") rather than a compliance audit, which is both more effective and better for retention.
Draft a persuasive pitch to leadership to allocate a meaningful share of engineering capacity, for one or two quarters, to pay down systemic technical debt. Include the KPIs you would use to measure success, a cost-versus-benefit summary, risk mitigation if the allocation is granted, and how you would communicate the plan internally.
Sample Answer
Direct answer
A pitch that gets capacity funded has three parts: a quantified cost of inaction (what the debt is already costing, in metrics leadership tracks), a specific, time-boxed ask (not "more time," but "6% of capacity for two quarters"), and a way to prove it worked (KPIs measured before and after). Vague asks ("we need to pay down debt") lose to specific, revenue-adjacent asks every time.
Structured elaboration
- Cost of inaction, in leadership's language. Translate engineering signals into business terms: rising incident rate into customer-facing downtime and support cost, slowing deploy frequency into slower feature delivery, rising bug rate into churn risk. Use the metrics leadership already watches; don't introduce a new one that requires them to trust your framing.
- A specific ask with a number attached. "6% of engineering capacity for two quarters" is fundable because it can be compared against alternatives (a headcount ask, a different project). "We need time to fix this" is not, because it has no opportunity cost leadership can evaluate.
- Cost-versus-benefit summary. State the cost (capacity allocated, in engineer-weeks or a dollar-equivalent) against the expected benefit (fewer incidents, faster releases), even if the benefit is a range rather than a false-precision point estimate.
- Risk mitigation if granted. Show you've thought about what could go wrong with the allocation itself: scope creep, or debt work silently expanding to eat more than the agreed share, and state the concrete mitigation right here, not just the risk: cap scope creep with a fixed revisit date on the calendar and mandatory reporting of debt-capacity usage at every sprint review, so the allocation can't quietly become permanent or silently expand past the agreed share.
- Internal communication plan. How you'll keep the team and stakeholders updated during the allocated window, so the ask doesn't quietly become permanent or get silently descoped when the next deadline arrives.
Worked example
A pitch: "Our incident rate has risen 40% over two quarters, concentrated in the checkout service; each incident costs an estimated $8,000 in support load and lost conversions. We're asking for 6% of engineering capacity (roughly 1.5 engineers) for two quarters to address the top three contributing debt items, identified via our architecture-level debt review. Success criteria: incident rate in checkout back to baseline, and deploy frequency for that service back above 3/week. We'll report progress at each sprint review and revisit the allocation at the two-quarter mark rather than letting it continue by default."
Trade-offs & pitfalls
The most common failure is pitching in engineering language ("our cyclomatic complexity is too high") to an audience that doesn't have the context to weigh that against a competing revenue ask. The second is asking for an open-ended allocation with no revisit date, which erodes trust the next time you need to ask, because leadership can't tell if the previous ask ever "finished."
Unlock Full Question Bank
Get access to all Technical Debt Management and Refactoring interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.