Web Development

Technical Debt: What It Is and When to Pay It Down

Technical debt is the future cost of shortcuts taken to ship sooner. Here is how to recognise it and decide when to pay it down.

Quick answer: Technical debt is the extra work you will owe later because of shortcuts taken now: rushed code, missing tests, outdated platforms or undocumented decisions. Some debt is deliberate and useful; unmanaged debt slows every new feature. Pay it down when interest (slow delivery, outages, hiring friction) exceeds the value of shipping something else instead.

The metaphor comes from software engineering: like financial debt, you can borrow time by doing the quick thing, then pay interest until you refactor, replace or document properly. This glossary keeps the idea practical for business owners and product leads, not only engineers.

What technical debt looks like on real projects

  • A CMS plugin stack nobody dares to update
  • Copy-pasted payment logic in three places that diverge
  • A “temporary” CSV import still running years later
  • Missing staging environments so every change is tested in production
  • Hard-coded credentials in a repo
  • A monolith where every small change risks unrelated modules
  • Design systems that exist only in a designer’s head

Debt is not the same as “code I dislike.” Mature, boring code that works can be low debt. Clever new code without tests can be high debt.

Related ideas appear when teams plan a legacy system modernization or a code audit: you are inventorying interest payments.

Deliberate vs accidental debt

Deliberate debt: you ship a manual process for invoicing to validate demand, knowing you will automate later. You write that decision down.

Accidental debt: the project grew without standards; nobody chose the mess, it accumulated.

Bitrot debt: the world moved (PHP versions, TLS rules, API deprecations) and the system did not. See also PHP version on WordPress and security timelines such as the TLS 1.0 PCI deadline.

Deliberate debt can be rational. Accidental and bitrot debt need scheduled attention.

The “interest” you actually feel

Interest shows up as:

  • Estimates that keep growing for similar features
  • Fear of deploying on Fridays
  • Only one person who understands a subsystem
  • Rising incident counts
  • New hires taking months to become productive
  • Security patches delayed because upgrades break custom hacks

If none of that is happening, you may be over-worrying about tidy abstractions. If all of it is happening, new roadmap items are fantasy.

When to tolerate debt

Tolerate (temporarily) when:

  • You are testing a market hypothesis with an MVP
  • The affected code path is rarely touched
  • A hard deadline protects a real business event and you have a written paydown plan afterwards
  • Replacement is already scheduled and polishing the old path would waste effort

Always record the debt: ticket, owner, trigger for revisit. Untracked debt is how temporary becomes permanent.

When to pay it down

Prioritise paydown when:

  • The area changes often (high interest)
  • Security or compliance requires it
  • Debt blocks revenue features you need this quarter
  • Key-person risk is unacceptable
  • Platform vendors set end-of-life dates

Good paydown is incremental: extract a module, add tests around a dangerous area, upgrade one runtime version, replace one brittle integration. Big-bang rewrites often create a second system while the first still runs, doubling cost. Prefer strangler patterns and staged data migration when replacing systems.

How to talk about debt with non-engineers

Avoid moralising (“the old team was sloppy”). Use operations language:

  • “This checkout change is three days if we patch the tangle, or one day after a two-day cleanup that also speeds the next three checkout tickets.”
  • “We can keep shipping on the current PHP version until date X; after that, hosting and security support become the risk.”

Connect debt to outcomes leaders already track: uptime, lead time, conversion, audit readiness.

A lightweight inventory method

  1. List systems and components (site, CRM sync, billing, admin tools).
  2. Score each on pain (1 to 5) and change frequency (1 to 5).
  3. Multiply for a rough priority signal.
  4. Attach known risks (security, vendor EOL).
  5. Schedule a fixed percentage of each sprint or month for the top items (for example, 15 to 20 percent), not only leftover scraps.

This is not precise science; it is a shared map.

What paydown is not

  • Endless rewrite for taste
  • Adopting every new framework to feel modern
  • Stopping all feature work for six months without a milestone
  • “Optimising” before measuring

Balance matters. Product value and debt control share one capacity budget.

Examples of healthy paydown work

Concrete paydown tasks that usually repay themselves:

  • Add characterisation tests around checkout before refactoring discounts
  • Split a 2,000-line template into components with clear inputs
  • Replace a brittle screen-scrape with a documented API client
  • Move secrets from code into environment configuration
  • Upgrade PHP on staging, fix deprecations, then promote
  • Delete dead feature flags and unused plugins

Each item should have an acceptance check (“deploy succeeds, regression list passes”). Vague tickets like “clean up code” rarely survive roadmap pressure.

Debt and agencies / vendors

When you hire an external team, ask how they will leave the codebase:

  • Is there a staging environment?
  • Are dependencies pinned and updateable?
  • Do you get documentation for cron jobs and integrations?
  • Who owns plugin licence renewals?

Cheap launches that skip those answers are how debt gets outsourced to your future self. Build handoff into the statement of work.

Relating debt to build-vs-buy

Sometimes the right paydown is deletion: replace a custom module with a maintained SaaS or plugin, migrate data, and turn the old code off. That is still engineering work (data migration included), but it can cut interest dramatically compared with polishing a bespoke dead end. Compare options with a clear total cost, similar to custom software vs off the shelf thinking.

Measuring whether paydown worked

After a paydown slice, check leading indicators: deploy frequency, mean time to recover from incidents, onboarding time for a new developer on that module, and count of “urgent hotfix” tickets. You will not always see a dramatic chart, but teams usually feel the difference when fear of touching a subsystem drops. If nothing improved, the wrong debt was targeted; revisit the inventory scores.

A closing distinction: debt vs risk

Not every scary system is “debt” in the shortcut sense. Some risks come from vendor lock-in, single points of failure in hosting, or missing monitoring. Label those clearly so you do not pretend a refactor fixes an infrastructure gap. Monitoring, backups and access control often reduce risk faster than rewriting application code. Mix both in your plan.

FAQ

Is using a CMS technical debt?

Not inherently. An unmaintained CMS with abandoned plugins is. A supported CMS with updates and backups can be a sound choice.

Should we rewrite from scratch?

Only with clear boundaries, data migration plans and a period where old and new coexist. Most teams underestimate porting hidden business rules.

Who owns technical debt?

Product and engineering together. If only engineers care, debt loses budget. If only product cares about features, interest explodes.

Can agencies add debt?

Yes, through rushed launches without docs or tests. Ask for handoff notes, staging and update paths in every statement of work.

Next step

If delivery has slowed or upgrades feel scary, start with an honest inventory rather than a vague rewrite wish. Our custom development work includes pragmatic modernisation plans that respect both roadmap and interest payments.

About the author

Imran M

Leave a Reply

Your email address will not be published. Required fields are marked *

Ready to improve your website?

Let's build a faster, higher performing website.