Paying off Technical Debt

Technical DebtTechnical debt is very similar to consumer revolving debt.  It’s convenient, especially when you’re resource or time constrained.  But it has an ugly compounding effect, and must therefore be managed as often and as early as possible.  The long term effects of the compound “interest” of technical debt can cripple and eventually kill a company’s ability to innovate and iterate through its product goals.

How Does Technical Debt Work?

Let’s suppose you’re with a startup trying to quickly bring a product to market.  Everyone in the organization lives and breathes iterative product development, constantly reminding each other how Lean and Agile the company is.  The single most important thing is to put product in front of customers, and validate the business strategy by monetizing it.  Because the process is continuous and iterative, there’s no need to get it 100% right the first time – you can always fix it in the next iteration (“sprint”), and if the customer doesn’t bite, you can pivot quickly to adapt to that.  In theory this is an incredibly powerful methodology.  What used to take months or years of sequential requirements gathering, design, development, and testing now takes weeks.  Most importantly, market validation comes very quickly – it’s not a huge bet with one shot anymore.  As long as your vision is sound, you are solving real problems the market actually cares about, and your team is talented, you can iterate and pivot your way to success faster than every before.

While all this velocity gets everyone excited, the engineers are charging the technical “credit card” to get it done.  In most cases it starts off innocently enough.  Problems are defined very tactically, with limited scope.  Everyone advises against “boiling the ocean” and overthinking solutions.  Your engineers go off and get the job done, satisfying the requirements and scope for each iteration with ease.  The problem is software development is a delicate blend of art and science, and it’s certainly not black and white.  In order to narrow focus on a solution, developers often have to ignore (or postpone) broader architecture.  Too focused, and the code works only for very limited use cases, which will no doubt expand in scope as time goes on.  This means lots of duplicate efforts to address related problems in future iterations.  In consumer terms, you just charged a shiny new gadget on a high interest credit card.  If on the other hand the implementation is too broad, it takes too long to hit the market for validation and defeats the purpose of Agile and Lean.  This is like saving up over time to pay cash for the shiny new gadget.  Time is an enemy few startups can afford to capitulate to, which is why…

You Can’t Build a Startup Without Technical Debt

Let’s all accept this.  Anyone who tells you their products are free of technical debt is either ignorant or delusional.  While consumers can decide not to charge credit cards, startups cannot avoid taking short cuts to bring products to market, and therefore incur technical debt.  It’s not shameful or even wrong to do this – in fact, if used properly, it’s a very effective tool.  In other words, think of it as low interest if used responsibly.  Did I mention it’s a lot like consumer debt?  Pay on time and your interest rates are low.  Pay late and suddenly you are dealing with a loan shark.  Just like in the consumer world, small technical debt can snowball to large, unsustainable sums thanks to the compounding effect.  When you build shortcuts on top of shortcuts, each iteration becomes less productive.  The financial minds will want to increase engineering headcount, but this is like raising a credit limit.  If it works at all, it’s just for a short time.  After that, the technical debt becomes larger and less sustainable.

Managing Technical Debt

As “bankruptcy” is not an option, and bill consolidation doesn’t really apply to technology, you’re better off managing technical debt regularly.  Here are 3 general guidelines to follow:

  1. Well Articulated, Forward-thinking Strategy: your Product Management and/or CTO types should actually articulate a long term combined technology and business strategy.  Of course in a Lean world, this changes regularly, but chances are it will become more and more consistent with each iteration.  Even though you can’t afford to architect everything properly up front, the company should still have a good idea of what future offerings will look like.  It’s imperative that everyone involved with product understands this, including the engineers themselves.  What problems are solved?  What use cases do customers have?  What are we likely going to have to support in the future?  Armed with this knowledge, the product and engineering teams can at least enjoy the benefits of context, which can enlarge the iterative problem solving focus just enough to reduce a lot of technical debt.
  2. Refactoring: fortunately, Agile already has a built-in answer to paying off technical debt.  Refactoring scares non-technical people because it implies lots of risk and lots of time, with no immediate tangible benefits.  It’s like selling an investment.  Financially sophisticated individuals understand the value of investing in the future even if it doesn’t deliver value right away.  You have to be able to articulate it this way when it applies to technology.  Thankfully, good engineers fully embrace and often even demand refactoring, so they’ve already bought in.  The biggest challenge is knowing when to refactor.  In some cases it makes sense to do it continuously as you go along.  In others it’s better to dedicate entire iterations to it.  Whichever way makes sense with your product and more importantly your team, the key is to take small bites.  Just like feature development, refactoring should be iterative.  This mitigates risk in quality and stability.
  3. Backlog: again, Agile has another secret weapon that you should be using all the time.  In most cases engineers know when they are taking shortcuts.  Many even take them reluctantly, and are not shy about letting everyone know they are implementing heinous hacks against their better judgment.  Knowing you have a problem is the first step to solving it, which is great.  But it’s not enough to recognize, you must also record this.  Engineers should be adding refactoring tasks to the backlog (or whatever makes sense in your Agile dashboard) for future consideration.  They should do this early and often.  This way you can keep track of the cost of your technical debt even if you decide to defer payment a little longer.  If you don’t do this, it’s like charging that credit card without even asking what the amount is.

Technical debt is a reality in our Lean startup world.  Companies that manage it effectively ensure they can continue to innovate at the pace the market demands for a long time.  Those that don’t end up with stalled, irrelevant products and eventually fail.

About Leo Reiter

Gen-X tech entrepreneur with over two decades in diverse fields of the software industry, and a passion for expressing myself to anyone who likes to listen
This entry was posted in Development, Leadership, Strategy. Bookmark the permalink.

One Response to Paying off Technical Debt

  1. Great post, Leo. A startup always takes on debts. Most early-stage companies are not revenue positive, so are burning through capital to explore a problem. Technical Debt is just one aspect of this, to be managed like other burns (as you point out). I’d go even farther: unless a market problem is completely understood, there’s no (practical) way of determining the correct form of a solution. At best are guesses which are often wrong. Hence, tech debt is an inevitable consequence of development.
    I weigh in on the “continuous refactor” model of handling tech debt. If code is sufficiently modularized, then refactoring isn’t “stop the presses”-type of development; it can often be done on a per-component basis as new learnings are incorporated into the product. At WebKite we’ve done refactors on things as basic as changes to permissions systems or fundamental model assumptions on the fly and in conjunction with regular feature development. It’s actually a test of your code’s modularization that it can support such changes without collapsing.

    Thanks for some great thoughts.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>