Technical debt & architecture decisions
Cunningham's debt metaphor and its misuse, deliberate vs accidental debt, ADRs, monoliths vs microservices, and Conway's law.
13 cards · 7 quiz questions · 8 min read
Every codebase is a record of decisions made under pressure, with incomplete information, by people who have often since moved on. Some of those decisions age well; others become the thing everyone complains about. This topic is about living with that reality honestly: understanding what technical debt really is, recording why decisions were made, choosing architectures on their merits rather than fashion, and noticing how much your organisation shapes your software.
Cunningham’s original metaphor
Ward Cunningham introduced the debt metaphor in a 1992 OOPSLA experience report about a financial application, WyCash. He was explaining to business-minded colleagues why the team kept reworking code that already functioned.
His idea was specific. When you ship software, you ship your current understanding of the problem. That’s good: getting it out lets you learn. But as you learn, the code’s structure drifts away from what you now know to be true. Shipping early is like borrowing money: it accelerates you. Refactoring the code to reflect your new understanding is repaying the loan. If you never repay, you pay interest instead, in the form of every change being slower and riskier than it should be.
How the metaphor gets misused
Over time, “technical debt” became a catch-all for any code someone dislikes, and sometimes a justification for writing sloppy code with a vague promise to clean it up. Cunningham later clarified that he never meant it to excuse poorly written code. His debt was clean code built on an understanding that later turned out incomplete.
That doesn’t make the broader usage useless, but it’s worth being precise. Calling everything debt hides important differences, and “we’ll pay it back later” is only a real plan if later actually arrives.
Deliberate versus accidental debt
A useful distinction is how the debt arose:
- Deliberate debt is a conscious trade-off. “We’ll support one currency for launch and generalise next quarter.” It can be recorded, estimated and scheduled.
- Accidental (inadvertent) debt accrues without anyone choosing it: a design that seemed right until requirements changed, a pattern the team didn’t know about yet, or gradual erosion as many small changes pile up.
Martin Fowler later added a second axis, prudent versus reckless, producing a quadrant. “We don’t have time for design” is reckless and deliberate. “Now we know how we should have built this” is prudent and inadvertent, and it’s arguably unavoidable in any project where people learn.
Paying it down wisely
The metaphor also suggests how to prioritise. Interest is only paid when you touch the code. A tangled module nobody has changed in two years charges almost nothing; a messy core module edited every week charges constantly. Direct effort at hot spots, where change frequency and pain overlap, rather than at whatever looks ugliest.
Architecture Decision Records
A recurring source of accidental debt is lost context. A new developer finds an odd choice, doesn’t know why it was made, and either tiptoes around it forever or “fixes” it and reintroduces the problem it solved.
In 2011 Michael Nygard proposed Architecture Decision Records: short text files, stored in the repository, each capturing one significant decision. A typical structure:
# ADR 7: Use PostgreSQL for order storage
Status: Accepted
## Context
Orders need multi-row transactions; the team knows SQL well...
## Decision
We will store orders in PostgreSQL.
## Consequences
Strong consistency and familiar tooling; horizontal write
scaling will need more work if volume grows 50x.
The context and consequences sections do the heavy lifting: they record the forces at play and the downsides knowingly accepted. ADRs are append-only. When a decision changes, you write a new record and mark the old one superseded, so the history of reasoning survives.
Monolith versus microservices
Architecture discussions often treat microservices as the grown-up destination and monoliths as a stage to outgrow. That framing is a mistake; they are different trade-offs.
A monolith is deployed as one unit. Calls between components are in-process and cheap, transactions are straightforward, debugging follows one stack trace, and refactoring across modules is an IDE operation. Its weaknesses show at scale: many teams contending over one deploy, build times growing, and the temptation for boundaries to blur.
Microservices split the system into independently deployable services, each owning its data. That lets many teams ship without coordinating, and lets hot components scale separately. The price is steep: network calls that fail and add latency, consistency across separate databases, versioned interfaces, distributed tracing to debug anything, and a large operational platform.
Microservices mainly address an organisational scaling problem. If you don’t have that problem, you pay the costs without collecting the benefit.
A common, pragmatic path is a modular monolith with clear internal boundaries, extracting services only when a concrete need appears. Service boundaries drawn before you understand the domain are expensive to move.
Conway’s law
In his 1968 paper “How Do Committees Invent?”, Melvin Conway observed that organisations designing systems tend to produce designs that copy their own communication structures. The folklore example: give a compiler to three teams and you’ll get a three-pass compiler.
The mechanism is mundane. Interfaces between components need negotiation, and negotiation is easy within a team and hard across teams. So module boundaries settle where team boundaries already are. Separate frontend, backend and database teams tend to produce rigid layers with awkward handoffs.
This cuts both ways. It warns that a microservices architecture won’t hold if the organisation doesn’t match it. It also suggests the inverse Conway manoeuvre: design team boundaries around the architecture you want. Brooks made a related point in The Mythical Man-Month: communication overhead grows quickly with team size, and a system’s conceptual integrity depends on how its people coordinate.
The durable lesson
Debt, decisions and architecture are all about trade-offs made over time. Take on debt knowingly, write down why, choose structures for the problems you actually have, and remember that the org chart is part of the design.
Which best matches Ward Cunningham's original intent for the technical debt metaphor?
Sources
- Ward Cunningham — The WyCash Portfolio Management System (OOPSLA '92 experience report) author Where the technical debt metaphor was first introduced, in 1992.
- Michael Nygard — Documenting Architecture Decisions article 2011 post proposing lightweight Architecture Decision Records.
- Melvin E. Conway — How Do Committees Invent? paper 1968 Datamation article containing the observation now known as Conway's law.
- Frederick P. Brooks Jr. — The Mythical Man-Month book Classic essays on conceptual integrity, communication overhead and system structure.