Tied Inc.
Technical debt Tech DD Due diligence Startups Investment decisions

What technical debt actually is — and the patterns that hurt startups

Tied Inc. 日本語で読む

Most investors and M&A professionals know that “technical debt always exists.” Far fewer can articulate which kinds of debt arise at which stages, and why they hurt startups in particular. In tech DD, evaluating technical debt as a binary “exists or not” produces no useful judgment.

This article organizes technical debt into three categories, explains the accumulation mechanics specific to startups, and presents a framework you can use for investment and acquisition decisions.

A three-category taxonomy of technical debt

The most-cited reference is Martin Fowler’s 2009 “Technical Debt Quadrant” (intentional/accidental × prudent/reckless), widely known as a way to organize the nature of debt. In an investment and DD context, it becomes more practically useful when you add a perspective on where the debt originated.

Intentional debt Origin Speed-prioritizing trade-offs Evaluation lens Is there a repayment plan? Managed debt -> Often acceptable Accidental debt Origin Lack of knowledge or experience Evaluation lens Is there an improvement loop? Treated as an issue of capability and process Environment-driven Origin Obsolescence from growth or external change Evaluation lens Redesign plan and priority Right at the time. Treated as growth cost
Figure 1: A three-category taxonomy of technical debt

1. Intentional debt

Debt that arises when decision-makers knowingly choose a trade-off whose future cost they understand. A startup that skips proper design to validate initial PMF, or chooses a stop-gap implementation to make a release deadline, is taking on intentional debt.

Concrete examples: “we shipped to production with error handling stripped out to make the investor demo,” “we deferred the user authentication design and put login on raw IDs and passwords,” “we picked a simple data structure that ignores scalability so we could test the hypothesis.” All “we knew, and we chose.”

The essence of intentional debt is that it is a loan, and a loan is not inherently bad. The problem arises when principal and interest pile up without a repayment plan.

2. Accidental debt

Debt that accumulates unintentionally because of a gap in knowledge or experience — what “you would know if you knew it” was simply not known by the developers at the time.

Common cases: design mistakes that arose from advancing implementation while requirements were ambiguous, wrong library choices, the absence of a testing strategy.

Examples: a backend engineer who also picked up frontend work without knowing React state-management patterns built deeply nested data passing across components; an engineer using an ORM didn’t notice an N+1 query problem (queries firing inside a loop) and triggered a performance incident in production; an authentication feature was implemented with a flawed session-management design that later required a foundational rewrite. The common thread: “you would have avoided it if you had known.”

Accidental debt is to some degree acceptable as “learning cost,” but if the same mistakes recur as a pattern, the issue lies in engineering capability and the development process itself.

That said, with the spread of AI coding assistants, this category may decline gradually over time. Tools like GitHub Copilot and Claude Code can flag N+1 problems, point out security mistakes, and suggest better design patterns in real time. Some “you would have avoided it if you knew” mistakes will become rarer as AI fills the gap. There is, however, a counter-risk: uncritically accepting AI suggestions can create a new flavor of accidental debt. The importance of review does not change.

3. Environment-driven debt

The category startups most often miss. It covers cases where a design or technology choice that was correct at the time becomes debt as the business scales or the market shifts.

  • Scale wall: A database structure designed for hundreds of users becomes the bottleneck at hundreds of thousands.
  • Organizational wall: A codebase that two or three people shared comfortably explodes into merge conflicts when ten people work on it in parallel.
  • External-dependency collapse: A SaaS or open-source choice that was the best at the time becomes debt due to direction changes, price changes, or end-of-support.

The crucial point is that environment-driven debt was the correct choice when it was made. It is not a problem to blame on prior engineers, but a structural cost that arises with growth.

Startup-specific debt accumulation mechanics

Compared to enterprise software development, startups carry structural factors that cause technical debt to accumulate quickly.

Four reasons technical debt piles up in startups (1) Speed-first culture Once "ship at all costs" hardens into culture, intentional debt stops being visible -> "We'll do it later" becomes "never" (2) No CTO, or shared CTO role Technical direction lacks consistency, design philosophies blur in the codebase -> Accumulates as "complexity," not "volume" (3) Pivots leave residue Dead code from old features lingers, creating learning, dependency, security cost -> "If it works, don't touch it" is dangerous (4) Knowledge concentrated in early hires Design context is never written down, and is lost when team members rotate out -> Context-free changes drive more complexity
Figure 2: Four reasons technical debt accumulates in startups

Speed-first culture

“Better to ship technically incomplete than to delay” is a rational stance in the early stage. Designing perfectly without market feedback is wasted effort if you end up pivoting.

But once this culture hardens, the act of taking on technical debt stops being visible as a decision. The unspoken understanding “we will do this later” gets shared, and “later” never arrives.

No CTO, or shared CTO role

In the early stage of a startup, the CEO often doubles as CTO, or an engineer carries technical responsibility without a formal title.

In this state, technical direction lacks consistency. Each engineer hired tends to bring a different approach, and the result is a codebase whose styles and design philosophies are blended together. This kind of debt accumulates as “complexity” rather than “volume,” which makes it harder to surface after the fact.

Pivots leave residue

Startups pivot — they change their business model and their feature set. Often the code from the discarded features is not fully removed. It sits in the codebase as “unused but still present.”

This is dead code, and leaving it generates the following costs.

  • Learning cost for new engineers (“what is this for?”)
  • Complicated dependencies (dead code intertwined with live code)
  • Security risk (dependence on unmaintained code)

Knowledge concentrated in early hires

Founding engineers and early hires hold the background knowledge of why each design was chosen. But that knowledge is rarely written down, and stays in their heads.

When the team grows and early members leave, that context disappears, and subsequent engineers continue making changes without understanding “why it was built this way.” This drives further complication.

Practical responses to each factor

The four factors above are nearly unavoidable as a startup grows. The problem is not the accumulation itself but failing to recognize the accumulation. There is something practical you can do for each factor, even without a perfect fix.

Even with speed-first development — record the trade-off as it happens. A single line of comment on the issue or PR — “this implementation is interim because of X; redesign in phase Y” — is enough to convert debt from “invisible borrowing” into “managed borrowing.” Notion, GitHub Issues, Linear — any of them works.

Even without (or with a part-time) CTO — coding standards and review baselines are increasingly things you can offload to AI. Static analysis tools like ESLint and Prettier, combined with GitHub Copilot or Claude Code in the review process, can preserve a baseline of design quality automatically without a dedicated CTO. The realistic split is to have humans focus on the design decisions that require judgment and let AI handle conformance checking.

Even with pivot residue — you do not have to wipe unused code immediately. The first move is to label dead code as such in comments, then run a quarterly cleanup sprint to inventory unused code. Visibility comes before deletion.

Even with concentrated knowledge — adopt the habit of writing ADRs (Architecture Decision Records). A short note recording “why we chose this design and the trade-offs against the alternatives” dramatically reduces context loss when early members leave.

Knowing the accumulation mechanics is itself valuable to investors and M&A professionals. Identifying which of these factors is generating debt in a given organization lets you estimate repayment difficulty and the resources required with much greater accuracy.

Evaluating debt that you cannot put a number on

A challenge with technical debt is that, unlike financial debt, you cannot quantify principal and interest. There is no “the technical debt is 10 million yen.”

So how do you evaluate it in an investment or DD context? Combine the following three perspectives.

Trend in development velocity

Look at release cadence and time-per-feature over the last 6–12 months. If team size has not changed but release cadence has slowed and feature delivery has stretched, debt accumulation is most likely the cause of the velocity drop.

A useful question is: “compared to one year ago, how much longer does it take you to build a comparably-sized feature?”

That said, small and mid-sized startups often do not record engineering effort precisely, so an actual measurement may be hard to obtain. The following alternatives apply.

  • Read the trend from Git commit and PR history: With repository access, you can confirm month-over-month commit and PR-merge counts in minutes. If commit frequency is trending down with the same headcount, something is creating friction.
  • Engineer interviews: An open question — “have you noticed work that used to be easy now feeling hard?” — surfaces velocity changes even without quantitative data.
  • Cycle time in task management tools: If JIRA, Linear, or GitHub Issues are in use, the time from open to close (cycle time) is a proxy for development velocity over time.
  • Felt experience of leadership and engineers: Whether leadership and engineers agree on “do releases feel slower than before?” is itself a data point. A wide gap between the two often means debt is invisible to one side.

Test coverage and incident frequency

Low automated-test coverage combined with incidents on every release is a sign that “the cost of change” is high.

Test coverage comes in several forms.

Coverage typeWhat it measuresBenchmark
Line coverageShare of lines executed by tests80%+ is a common goal
Branch coverageWhether each branch (if/else) was executedStricter than line coverage
Function coverageShare of functions invokedVerify no critical functions are missed
Statement coverageShare of statements executedClose cousin of line coverage

A caveat: “high coverage” does not necessarily mean “high quality.” Tests without assertions (without verifying expected values) inflate coverage without providing real protection. In DD, what matters is not just the number but whether tests are protecting the right things — coverage on core business logic, payments, and authentication deserves particular attention.

When teams keep adding features without tests, “I fixed it and broke something else” loops grow, and the team becomes afraid to change anything (this is often called change phobia). At that point, the codebase keeps growing in size but the actual development capability has dropped.

Engineer attrition trend and hiring difficulty

In an organization with severe technical debt, the strongest engineers tend to leave first — adverse selection. Highly-marketable engineers are most likely to think “I don’t want to work in this codebase.”

Hiring also gets harder; a debt-laden codebase raises the bar for candidates. Pay attention to candidate reactions to the codebase during code-review interviews and shadowing — that reaction is itself a useful indicator.

Quantitative evaluation with static analysis

The three lenses above measure outcomes. Measuring the codebase directly — either by asking engineers for access or having a technical specialist run analysis as part of DD — gives you a more direct estimate of debt size.

Cyclomatic complexity

Proposed by Thomas J. McCabe in 1976, cyclomatic complexity counts the number of independent control-flow paths through a program. Each if, for, while, case adds to the score. Common rules of thumb: 10 or below is fine; above 20 warrants attention; above 50 is dangerous.

Functions with high cyclomatic complexity have many branches that unit tests must cover — the act of writing the tests becomes hard. When low-coverage code overlaps with high-cyclomatic-complexity functions, those areas carry the highest change risk and should be evaluated first.

Cognitive complexity

Cognitive complexity, proposed by SonarSource in 2016, is designed to address cyclomatic complexity’s blind spot — that “the same number of branches can be very different to read depending on nesting depth.” Deeper nesting adds weighted score, more accurately reflecting the cognitive load on a human reader.

Even at the same cyclomatic complexity of 5, five sequential if statements are far easier to read than one with three levels of nesting. Cognitive complexity captures that difference numerically.

MetricProposer / yearWhat it measuresLimitation
Cyclomatic complexityMcCabe (1976)Independent paths in control flowIgnores nesting depth
Cognitive complexitySonarSource (2016)Difficulty for humans to readHard to compute without tooling

When many functions or methods carry high complexity scores, the code is more bug-prone on every change and more expensive to review. In DD, “what share of all functions exceed the high-complexity threshold” is a useful single metric.

Estimating debt from function and code-size data

Looking at the overall codebase size (SLOC: Source Lines of Code) along with the count of functions, classes, and modules reveals the “density of complexity.” A 10,000-line system with 500 functions and a 10,000-line system with 50 functions tend to behave very differently — in the latter, individual functions have ballooned in role and become harder to maintain.

Likewise, if the average function or method length is long (a rough cutoff is 50+ lines for many functions), single-responsibility is likely being violated, and the blast radius of any change becomes hard to read.

Static analysis tools like SonarQube and SonarCloud

SonarQube (open-source self-hosted) and SonarCloud (cloud) visualize cognitive complexity, code duplication, security hotspots, and test coverage in dashboards. When integrated with CI/CD, a quality gate runs on every PR and increases in debt are caught automatically.

In a DD context, whether the target company has adopted and operationalized this kind of static analysis is itself a maturity signal. Even when no tooling is in place, an initial scan can be run in a short time given repository access. Other options exist for specific use cases — Code Climate, or CodeQL which integrates with GitHub.

ToolPrimary useForm
SonarQube / SonarCloudCombined complexity, duplication, security viewOpen-source or SaaS
Code ClimateMaintainability score, technical debt timeSaaS
CodeQLDeep static analysis for security vulnerabilitiesGitHub-integrated

Distinguishing fatal debt from acceptable debt

Not all technical debt carries the same risk. Use the following criteria to grade severity.

Localized or pervasive

Debt confined to a specific module or feature has bounded refactoring scope, so repayment cost can be estimated. By contrast, when a flawed design philosophy permeates the whole system — say, security has been treated as an afterthought everywhere — partial improvement becomes very hard.

Whether a repayment roadmap exists

“We know this part is technical debt and plan to address it in phase X” is managed debt. Without a repayment plan, the debt is not even an item of management discussion — it has been made to “not exist.”

In DD, whether you get a concrete answer to “which debt item is most important and when do you plan to address it?” is one indicator of organizational maturity.

Whether security and compliance are involved

For products handling personal information, payments, or medical data, security-related debt requires immediate evaluation. The cost of an incident — response, damages, reputational loss — significantly exceeds the cost of remediation.

Security debt discovered after investment or acquisition can become subject to clawbacks (damages) or deal renegotiation.

Defining “fatal debt”

Combining the three criteria, debt that meets any one of the following is “fatal.”

  1. Cannot be repaid incrementally: Cannot be addressed by partial refactoring; requires a full architectural rewrite. Because parallel migration alongside the existing system is not feasible, it carries business-interruption risk.
  2. Security or compliance risk that can crystalize at any moment: Debt that could lead to data breach, unauthorized access, or regulatory violation. Post-incident cost can be tens of times higher than preemptive remediation.
  3. Engineering organization can no longer reproduce itself: Technical debt has become so severe that strong engineers cannot be hired or retained. The organization loses access to the very people who could fix the codebase, and the debt accelerates downward.

Conversely, debt that is localized, has a repayment plan, has no security risk, and has limited impact on hiring can be treated in DD as “manageable debt.” Whether debt is fatal is determined not by its existence, but by whether the organization is in a state to face it.

Case studies: typical accumulation patterns

Pattern 1: Design frozen around PMF

Teams that rushed to PMF in the early stage sometimes continue to extend features on top of the “pre-PMF design” even after the business is validated. The initial design was meant for a small validation set of users; it never considered scalability.

Signals of this pattern:

  • Indexes on the database are inadequate; queries slow as users grow
  • Authentication and authorization are running in production in a “this works for now” state
  • Features are crammed into a monolith, and isolated changes ripple into unrelated areas

Difficulty of remediation is high. A full design overhaul requires staged migration while the existing features stay live, alongside ongoing feature work — a multi-month to multi-year resource commitment.

Pattern 2: Architecture friction at organizational scale

When a team grows from three or four people to ten or more, dividing the codebase becomes hard. With a single repository, database, and deployment pipeline shared across everyone, change conflicts, test environment contention, and deployment queues become the daily reality.

Signals:

  • PR merges take a long time and merge conflicts are constant
  • Test execution time exceeds 15 minutes; CI wait time is the bottleneck
  • Multiple “only X-san understands that area” pockets exist

The typical remediation is microservices decomposition or domain partitioning, but because organizational structure and architecture must change together, the work has to be staged.

Pattern 3: Concentrated external dependencies

A specific SaaS or open-source choice has been baked deeply into the design, and that service becomes hard to keep using due to price changes, feature retirement, or acquisition.

Common examples:

  • Tight coupling to a particular email-sending service
  • An old open-source framework whose support has ended
  • Direct dependency on a generative-AI API (model changes, price changes, API spec changes)

This kind of debt only crystalizes when the dependency itself changes. In DD, verify “the substitutability of major infrastructure and SaaS” and assess migration cost and difficulty.

Pattern 4: Debt from outsourced development

A company without in-house engineers commissioned a development firm or freelancer to build the application and inherited the delivered code as is.

The reason this pattern bites particularly hard is that the rationale behind design decisions does not exist inside the company. Why the vendor chose this design, what constraints they were working under, which parts are interim — none of that context arrives with the code, and the cost of later changes balloons.

Signals:

  • No documentation, sparse code comments
  • No engineer in the company can read the code from scratch
  • Quotes for bug fixes and new features rose sharply after the contract with the vendor ended
  • Code quality standards (tests, naming, design) deviate sharply from the rest of the company’s code

In DD, the starting point is to confirm “who wrote it, are there handover docs, is anyone in-house able to read it?” In the worst case, the vendor’s code is so opaque and so bound to the original team that effectively a rewrite is required.

Pattern 5: No-code, low-code, or unfamiliar stack adoption

A non-engineer or unfamiliar engineer chose a no-code tool, low-code platform, or a stack the team doesn’t know in order to launch quickly.

No-code and low-code tools (Bubble, Webflow, Adalo, etc.) are effective for initial launch, but once business growth demands more product complexity, the following issues surface.

  • Customization ceiling: Platform constraints prevent the implementation of needed features
  • Vendor lock-in: Platform price changes or service termination become direct business risks
  • Hidden migration cost: When a code-based migration is considered, the design cost of “what gets rebuilt and how” is a separate, large project

Unfamiliar-stack adoption produces similar problems. When a team that does not know a language or framework picks it up because “it’s popular” or “the candidate said they used it,” implementation quality is low and unintelligible code piles up for the next engineer.

The DD checks: “why did the team choose the current stack?” and “how many engineers in the team are proficient with it?” If the rationale is vague and proficient people are scarce, the situation should be evaluated as analogous to environment-driven debt.

Wrap-up: making the habit “classify and evaluate debt”

Technical debt is not something to judge as “exists or not.” It is something to classify and evaluate by “which kind, accumulated at which stage, and at what scale.”

CategoryCauseEvaluation lens
Intentional debtSpeed-prioritizing trade-offsIs there a repayment plan?
Accidental debtLack of knowledge or experienceIs there an organization-level improvement loop?
Environment-driven debtGrowth or external changeRedesign plan and priority

In startup tech DD, what matters most is not the quality of the code itself, but whether the organization has the capability to recognize, manage, and repay the debt.

For the underlying concept of technical debt, see What technical debt actually is: a redefinition for investors and operators. For tech DD evaluation lenses beyond debt, see The big picture of technical due diligence and seven evaluation lenses.

For evaluation of an investment or acquisition target’s engineering organization or hands-on tech DD support, see TiedPro for investors, or contact us directly.


FAQ

Q. Can technical debt be evaluated by non-engineers?

Classification and severity assessment can be done to a meaningful degree by non-engineers. “Is there a repayment plan?” “What is the velocity trend?” “Who holds the institutional knowledge?” — these are accessible from a management and finance lens. That said, evaluating the specific technical structure (dependency density, testing strategy, security design) benefits from a technical specialist on the team.

Q. How much resource does repaying technical debt take?

It varies enormously by scale and category. Localized accidental debt can often be improved by directing 15–25% of engineering capacity for three to six months. Structural debt that pervades the design can require continuous effort over one to two years. Because the cost estimate itself becomes input to investment judgment, we recommend doing a detailed inventory with engineers during DD.

Q. Should we avoid investing in companies with a lot of technical debt?

Not necessarily. The thing that matters is whether it is being managed. Organizations that recognize their technical debt, prioritize it, and have a repayment plan can in fact be evaluated as more mature in technical management. The problem cases are those that do not see the debt at all, or that see it but lack the will or capability to repay it.

Tied Inc.

Tied Inc.

Tech-leadership advisory for investors and operating companies. We support technical due diligence, value-up engineering, and strategic technology decisions across the investment lifecycle.

Get in touch →