This is a follow-up to Why Tech Debt Never Gets Repaid — It’s Not Visibility, It’s Incentives. That article argued the blocker is structural: the party responsible for delivery quality has no authority over the schedule. It ended with three conditions any structural fix would have to satisfy. This one describes how the Albatross Method satisfies them.
Most writing about technical debt ends with the same prescription: make it visible. Track it. Put it in the same system as features. Dedicate sprint time to it.
The previous article argued that this prescription fails, because visibility is not the blocker. The blocker is structural. In Scrum, the Product Owner owns the schedule and is measured on feature value; debt repayment produces no visible value, so it loses the prioritization debate every time. In Kanban, there is no debate at all — debt is not a card, so it never enters the queue. Making debt visible does not give anyone a reason to repay it.
The previous article ended with three conditions any structural fix would have to satisfy:
- Debt has to have a place in the plan by default — not by argument, sprint after sprint.
- Debt has to be located, not just tracked — so you know whether it is repayable or systemic.
- The horizon has to outlast a sprint — long enough to hold a decision whose payoff is measured in quarters.
The Albatross Method was designed around those conditions. What follows is how it addresses them — and, before that, a distinction the standard advice never makes: the two different ways debt arises, because they call for different responses.
Prevent, Contain, Solve
Debt has a lifecycle. It is created, it spreads, and it is either repaid or it compounds. The Albatross answer maps onto each stage:
- Prevent — stop debt from being created unqualified.
- Contain — stop debt from spreading once it exists.
- Solve — give debt a position on the schedule before it becomes a crisis.
These are not three separate features. They are three consequences of the same thing: system design before construction.
One structural fact underlies all three: the dev team has its own backlog, independent of the Product Owner’s. Because the team has the freedom to make improvements, that backlog is at the team’s disposal. It is where debt gets a position on the schedule when the design and the moment call for it.
Two Ways Debt Arises
Before showing what Albatross does, it is worth distinguishing two origins of debt. Most advice assumes the first. The second is more common on serious projects, and it is structurally harder to catch.
Case A — Individual partial understanding
One person writes code with incomplete understanding. The shortcut is theirs, and the gap is local. This is the case Ward Cunningham’s metaphor describes — code written with partial understanding, which the metaphor says should stay clean enough to refactor as understanding improves.
It is not one scenario. It is a family of them, and most developers will recognize their own work in several:
- Unfamiliar territory. The developer is working in a domain, library, or framework they do not yet know well. They solve it the way that works, not the way that fits. Someone new to async writes a blocking call inside an async handler, and it passes review because it “works.”
- Under-specified requirement. The requirement was vague or contradictory. The developer made a reasonable interpretation and built to it. “Handle the error” produces a generic try/catch that swallows everything, because nobody said what the error cases actually were.
- Optimizing for the visible goal. The developer solves the stated problem and stops, without handling the cases the statement did not mention. “Add search” produces happy-path search with no pagination, no empty-result handling, no index.
- A reasoned shortcut under time pressure. The developer knows the right way and chooses the fast way anyway, intending to come back. The intent is rarely recorded. A hardcoded configuration value with a
// TODO: make this configurablethat never gets picked up. - Erosion by drift. The code was fine when written, but the surrounding system changed and it was not revisited. A helper that assumed a single-tenant model, quietly broken once multi-tenancy arrived.
- Tool or idiom mismatch. The developer brings a pattern from a previous stack that does not fit this one. A developer from a Java background writes deep inheritance hierarchies in a language whose community favors composition.
- Copy-paste over refactor. Two functions are needed that are very similar, and one already exists. Refactoring the existing function to share the common part is more effortful than copying it and modifying the copy. So the developer copies and modifies. The result works — but the two versions now drift independently.
Copy-paste deserves a closer look, because it behaves differently from the others. The new function is submitted on its own and reviewed on its own terms, and it looks fine. The duplicated portion is never compared against the existing version, because that version is not part of the submission. Nothing breaks when the copy is made. The cost arrives later, when the shared part needs a change — and now both versions must be modified, tested, and released separately. The cost scales with every additional near-duplicate.
This is the first subtype where the defect lives outside the piece. The gap is not in the new function’s logic. It is in the relationship between the new function and an existing one.
Why Case A resists complete prevention
Review is the natural defense against Case A. Most subtypes have a single author and a bounded scope, so the gap sits inside the piece, where a reviewer should be able to see it.
But review cannot be relied on to catch it all, because review is counter-cognitive work.
To judge a submission, the reviewer has to imagine what the code is doing — build a mental model of its behavior — and only then assess how well it does it. That is two inferences, not one observation. And the model must be built from scratch, in the reviewer’s head, from the code alone. The author already holds this model; the reviewer has to reconstruct it. That asymmetry is the whole difficulty.
Then there is the dependency surface. To verify correctness, the reviewer has to trace quite a number of dependencies — callers, callees, configuration, state, edge cases, and the assumptions the author never wrote down. Each is another thread to hold. Human working memory holds only a handful of items at once, and a review that requires holding a dozen interdependent facts is beyond reliable human performance, however skilled the reviewer. The burden is heavy, and it degrades under exactly the conditions where debt is most likely: long diffs, unfamiliar code, deadline pressure, tired reviewers.
The consequences are predictable. Review catches the shallow and local defects well — style, obvious bugs, clear misuse. It catches the deep and relational defects poorly — subtle incorrectness, wrong assumptions, and, as copy-paste shows, defects that live outside the submitted piece entirely.
So a meaningful share of Case A debt survives review. Not because reviewers are careless, but because the task asks more of human cognition than it can reliably deliver. Case A is a significant and permanent source of debt, even on teams with strong review culture. It cannot be fully prevented by discipline or effort. It needs structure that reduces what the reviewer has to hold in their head.
Case B — Collective misalignment
Now the harder case.
Several members each write their own component, each with adequate individual understanding. They assemble the pieces and find they do not add up — the interfaces do not meet, the assumptions conflict, the pieces were never designed to fit. Under time pressure, they take a loose compromise to make it work. That compromise becomes debt.
But it does not come from insufficient understanding. It comes from understanding arriving too late: each person understood their own piece, and the team understood the mismatch only at assembly. The rescue approach is itself a sign of good understanding — they saw the problem and patched it. But the patch is applied too late and is not good enough to be the design.
Why Case B matters more
Case B is not self-correcting under review. No individual submission is wrong. Each component is internally sound and passes review on its own terms. The defect exists only in the relationship between components — and that relationship is nobody’s submission. Standard per-piece review structurally cannot catch it. It surfaces at assembly, when the cost of fixing it properly is highest.
It is a coordination failure, not a competence failure, so better engineers and cleaner code do not fix it. The debt it produces is unqualified by nature: nobody chose the compromise as a design decision; it was an emergency fit. And it lives in the interfaces between components — the boundaries nobody owned — which is precisely why it spreads.
The boundary between them
Copy-paste is where Case A shades into Case B. It starts as an individual decision, but its defect lives in a relationship — between the new function and the existing one — that no single submission contains. It is the smallest instance of the same failure mode Case B exhibits at team scale.
Prevention: Debt as a Qualified Decision
Now the first mode.
Most debt is a decision — but not a proactive one. It is a give-in: a deliberate trade of quality for a deadline. That trade is not inherently wrong. Cunningham’s point was that a little debt speeds development if repaid promptly. The problem is not that the decision gets made. It is that it gets made without being identified, recorded, and eventually scheduled — no boundary, no scope, no record, no owner, no repayment condition.
And the give-in is easy to make, because there is no design requiring any of that. With no agreed design, there is nothing the shortcut can be measured against. No boundary to say “this debt sits here.” No scope to say “this is how far it reaches.” No condition to say “this is what repaying it means.” Without a design, the shortcut cannot be identified or recorded — only discovered later. The decision is made, but it leaves no trace. Unqualified debt is indistinguishable from drift.
System design first — diagrams, listing, team agreement — creates the reference the qualification needs. Every shortcut can be stated against the design: which component, which boundary, what scope, what repayment condition. The trade can still be made, but it enters the record as an identified and recorded decision.
For Case A, the design also reduces the reviewer’s cognitive load. The reviewer no longer reconstructs intent from code alone — the design states what the piece is supposed to do and how it fits. The reviewer compares the submission against an explicit model instead of building one. That is a different, lighter task, and it is the only way to make review reliable against deep defects.
For copy-paste specifically, the design activity is where similar code is identified. During design, the team enumerates functions and their relationships. That enumeration surfaces an existing near-duplicate before the new one is written. The question “should these share a common core?” is asked at design time, when refactoring is cheap, rather than at maintenance time, when it is expensive.
For Case B, the same design work is what makes the pieces add up before assembly. If the team agrees the interfaces, the assumptions, and the boundaries up front, the mismatch is caught in design rather than discovered at integration. The rescue compromise never has to be improvised, because the fit was designed, not hoped for.
Albatross’s prevention does different work in each case: in Case A it makes review tractable by supplying the model the reviewer would otherwise reconstruct; in Case B it catches what review structurally cannot.
The give-in is easy because there is nothing to qualify it against. Albatross supplies the something — before the pieces are built, not after they fail to fit.
Containment: Debt Has a Boundary by Construction
The previous article made a distinction that matters more than any tracking tool: confined debt is repayable; fixing a systemic debt can be more expensive than replacing it. Debt in a bounded component can be fixed without destabilizing the system. Debt that has spread into the interfaces can cost more to repair than to rebuild.
Prevention handles creation. Containment handles spread — the transition from confined to systemic. And it works because design-first work gives every piece of work a location before it is written. Shortcuts sit inside a component or cross a boundary, and the difference is visible because the boundary was drawn first.
Case B debt is the most dangerous for containment: it lives in the interfaces, exactly where no single component owns it. A qualified design makes those interfaces owned and visible, so spread can be observed.
The contrast is worth stating plainly. A backlog item that says “refactor auth module” tells you debt exists. A design artifact tells you whether it is still contained, and whether it is starting to cross boundaries.
Copy-paste: the same hazard in miniature
One duplicate is a small annoyance. Five near-duplicates of the same function are a maintenance trap — a single change now requires five coordinated edits and five separate test passes. The spread is the cost, not the first copy.
Containment works here in four ways:
- Design identifies the duplicate. The design activity enumerates functions and their relationships. That enumeration surfaces the existing near-duplicate — the second instance is recognized as a second instance before it is written.
- The boundary locates it. The copy sits either inside a component (contained, and repayable when that component is next touched) or across a boundary (already spreading, and visible as such).
- The horizon gives it a position. When the component holding the duplicate is next modified, the debt is repaid as part of that work — the same natural repayment trigger as any other recorded debt. No separate card, no separate debate.
- The rule is structural. The design specifies where shared logic lives. When a second instance is proposed, the design has already decided: this belongs in the shared core, not in a copy.
A duplicate is invisible if the only thing you look at is the diff. Design is where it becomes visible — and the design gives the debt a position on the schedule when the component is next touched.
Solve: Debt Gets a Position on the Schedule
This is the part the previous article could only gesture at. It is not enough to make debt visible or recorded; it has to have a position on the schedule, and repayment has to happen without depending on anyone’s memory or goodwill.
Debt Is Scheduled, Not a Debate
The hardest condition from the previous article: debt must be in the plan by default, not won by argument. If repayment depends on someone winning a prioritization debate every cycle, it will lose most of the time.
In Albatross, the dev team has its own backlog, independent of the Product Owner’s. Because the team has the freedom to make improvements, that backlog is at the team’s disposal. Debt gets a position on the schedule there — not as a separate list competing with features, but as part of the plan the team controls.
The question shifts from whether to schedule debt to when the boundary it sits in is next touched. The incentive problem does not vanish — it stops being the deciding factor. (Estimation and scheduling in Albatross carry this through the plan.)
And once the work is scheduled, the Product Owner has approved the end. As long as that end is kept, the Product Owner says nothing. The approval is what protects the work until it is done.
The Two Repayment Rules
Both rules are team-level. Neither depends on individual preference. And in both, the debt is always cared about — what differs is what triggers the repayment.
The structural rule — the primary path. Debt is repaid when its component is next modified, as part of that work.
The Product Owner is not thinking about implementation detail; they are thinking about features. When a feature requires modifying component X, X is now open. The developer is already in the code. The context is already loaded. The debt in X is visible against the design. And repaying it costs incrementally more than the feature work, not a separate allocation.
This is the structural rule: the design has already targeted the debt, and component modification triggers the repayment. It does not depend on anyone remembering to act.
The conscientious rule — the secondary path. Even when a component is not scheduled for modification, the dev team may decide to insert a debt fix.
This is a team decision made for the good of the software — not an individual’s preference, and not by whim. And “relevant enough” has a concrete test. If component A is targeted by a feature, and component B contains the debt, then B is on a dependency path of the targeted work when either A depends on B, or B depends on A. Either direction puts B in the blast radius of the change. Failing that, the debt may still qualify if its influence is strong enough that the team’s conscience urges a planned fix.
The structural rule handles what the design can plan. The conscientious rule handles what the design did not anticipate — made deliberately, by the team, on the basis of what serves the software.
| Structural rule | Conscientious rule | |
|---|---|---|
| Who decides | The design — already decided | The dev team |
| When repayment happens | When the component is next modified | When the team judges the fix serves the software |
| What triggers it | Component modification | The debt is on a dependency path of targeted work, or its influence is strong enough to prompt a planned fix |
| Individual preference? | No | No — it is a team judgment |
| What it covers | Debt the design located | Debt the design did not anticipate |
Debt is repaid in two ways, both team-level: by the structural rule, where the design targets the debt and component modification triggers repayment, and by the conscientious rule, where the dev team decides to insert a fix for the good of the software. Neither depends on individual preference.
Why the Alternatives Fail
Scrum cannot do this. The sprint is squeezed. Points are committed. The Product Owner asked for stories. Anything the Product Owner did not ask for is, by definition, out of scope. A developer who conscientiously adds a small debt fix is stealing from the sprint commitment — and will be asked to explain why the story is not done. There is no buffer, and no moment when debt is legitimately in scope.
Kanban cannot do this either, for a different reason. There is no sprint to steal from, but also no moment when the debt is in front of anyone.
Cards in Kanban represent individual work items — a task, a feature, a bug fix — not system functions or architectural components. A card might read “Add password reset endpoint,” not “auth module.” And debt is not a card unless someone creates one. The card that created the debt is done and gone. Fixing the debt requires creating a new card, writing it up, estimating it, and putting it in the queue.
Then the pull system works against it. Developers choose the next card, and the choice tends to favor cards that other future cards depend on. Debt blocks no future card. It is an internal quality fact about the code, not a process dependency. So it is rarely chosen.
And the creator may not fix it, for two reasons. The creator may have left — people change teams, change companies, move on. The debt is no longer theirs, and no mechanism assigns it to anyone else. Or the creator is always pushed to a prioritized feature — they still know the code, still could fix it, but their capacity is committed. Fixing the debt means working outside their assigned scope, or waiting for a debt card to be pulled. The problem is not ignorance. The creator often knows exactly what they did and why. The problem is that knowing does not schedule anything.
| Scrum | Kanban | Albatross | |
|---|---|---|---|
| Dev team latitude | Sprint capacity fully committed to stories; no buffer | No sprint, but no moment when debt is in front of anyone | The team has its own backlog, independent of the Product Owner’s; improvements are at the team’s disposal |
| What happens to small debt near the work | Cannot be added — the sprint is full; becomes a backlog item that must win a debate | Not a card; must be written up and queued, then rarely pulled | Gets a position on the schedule, by team decision |
| Who decides | The Product Owner, via the backlog | Whoever pulls the next card | The design (structural rule) or the dev team (conscientious rule) |
Repayment Is Designed, Not by Whim
The debt is repaid not because of a programmer’s whim, but because it is designed to be repaid in the system design. The repayment is a property of the design, not a property of the developer’s character.
| By whim | Designed repayment | |
|---|---|---|
| Who decides | The individual developer, ad hoc | The design, before the work begins |
| When it happens | When someone happens to notice and cares enough | When the component is next modified, as part of that work |
| What it depends on | The developer’s conscience and available time | The design’s specification and the plan’s structure |
| What happens if the developer does not care | Debt stays | Debt is still repaid, because it is part of the modification work |
Horizon: Debt Decisions Outlive Sprints
The third condition needs its own section, because the word is ambiguous and the condition is easy to misread.
Horizon, in this context, means the length of time a plan can hold a commitment before it resets and forgets.
A two-week sprint has a two-week horizon. When the sprint ends, the backlog is re-prioritized, and every commitment that did not fit is re-decided from scratch. Nothing carries forward automatically. The plan’s memory is two weeks long.
So “the horizon must outlast a sprint” means: a debt decision needs a container that persists across multiple sprints. If repaying a debt takes six weeks, and the plan can only hold two weeks of commitment, the decision has to be re-won three times — and it will lose at least once.
The horizon is not the duration of the work. It is the duration of the commitment. The work can still be done in two-week increments. What matters is that the decision to do it survives the increments.
Three things the horizon is not:
- Not a longer sprint. The problem is not that two weeks is too short to do the work. It is that a container that terminates cannot carry an unfinished commitment forward. At the end of a sprint, the backlog is re-ranked, capacity is re-allocated, and debt repayment — having produced nothing visible — is the first thing to go. Lengthening the sprint does not fix this; a four-week sprint still terminates and still resets. The structural problem is the reset, not the length.
- Not a roadmap. A roadmap is a list of intentions, not a set of commitments. A two-year roadmap can coexist with a two-week reset. The horizon has to live in the planning mechanism, not in a document.
- Not “estimate further out.” Estimation accuracy is not the point. The point is whether a decision can survive.
In Albatross, the planning horizon is defined by the commitment, not the calendar. A debt decision made in month one is still in force in month three — not because the sprints got longer, but because the plan does not reset at the sprint boundary. This is what Scrum structurally cannot do. It is not a discipline problem; it is a container problem.
The three conditions from the previous article are actually three kinds of persistence:
| Condition | What must persist |
|---|---|
| Debt in the plan by default | The category of work — debt is not re-argued each cycle |
| Debt located, not just tracked | The location of the debt — its boundary and owner |
| Horizon outlasts a sprint | The decision to repay — it survives the cycle boundary |
The horizon is specifically about the third kind: the decision’s ability to survive a reset. The first two are about how debt is represented; the third is about how long the representation lasts.
The three conditions are now answered in one place:
- Debt in the plan by default — the dev team’s backlog gives it a home, and the schedule gives it a position.
- Debt located, not just tracked — the design records its boundary, scope, owner, and repayment condition.
- Horizon outlasts a sprint — the plan holds the scheduled position, and the Product Owner’s approval protects it until the end is kept.
Why This Is Urgent Now: AI
There is a reason this matters more now than it did five years ago.
AI can write code faster than any team can read it. That is a crisis for methods that let structure emerge from construction, because emergent structure plus fast generation is unrecorded debt at machine speed. (How Albatross collaborates with modern AI tools covers the broader argument.)
Both cases scale badly. Case A — the subtypes of individual partial understanding — is now generated faster than review can catch, and review was already counter-cognitive and unreliable at scale. The volume of Case A debt rises with the volume of code, not with the number of engineers.
Case B scales worse. Multiple AI-assisted workstreams can produce components that do not fit, faster than any integration step can reconcile them. The mismatch surfaces at assembly, under the same time pressure as before, but now with more pieces to reconcile.
And AI is a copy-paste engine by nature. An agent that reads files on demand rather than indexing the whole codebase reconstructs structure by sampling. It may not know a near-duplicate already exists. Duplication that once took a deliberate act now takes a prompt — and the maintenance trap scales with every generation.
AI amplifies whatever structure you give it. A design produces located, recorded output. A backlog produces debt at scale.
What This Doesn’t Claim
Albatross does not eliminate debt. Some debt is correct — Cunningham’s original point was that a little debt speeds development if repaid promptly. What changes is that debt becomes identified at creation, recorded by the design, given a position on the schedule, and repaid by design.
That is the difference between debt you manage and debt that manages you.
The Question Worth Asking
If your team tracks technical debt and still does not repay it, the problem probably is not the tracking.
Ask instead: does the debt have a position on the schedule? For the dev team, it can — the team’s own backlog is independent of the Product Owner’s, and the team has the freedom to use it for improvements. Can the plan hold the decision long enough to act on it? It can: there is no fixed calendar end before scheduling, and once the work is scheduled, the Product Owner has approved the end. As long as that end is kept, the work holds.
And when repayment happens, is it because the structure triggered it — or because someone happened to care that day? The debt is always cared about. The structure triggers the repayment. Even under the conscientious rule, the trigger is a concrete condition: the debt sits on a dependency path of a targeted component — in either direction — or its influence is strong enough that the team’s conscience urges a planned fix.
Shortcuts that were taken to move fast eventually keep a team from moving fast — unless the plan gives debt a position on the schedule before it starts dragging progress.