I don’t want to answer the question of how technical debt is defined, or get into theoretical discussions on this topic. You can easily find the answers on Wikipedia and many other sources. I’d like to answer the question: what is technical debt in practice?
Technical debt arises at two points in the project. At the beginning, during the project quote and negotiations phase, and after the software has gone live.
Negotiations – a competition to be the cheapest
During negotiations, the client, even if they’re not looking for the cheapest contractor (I assume the best-case scenario), simply doesn’t want to pay above market rates - so they don’t choose the cheapest or the most expensive offer. They pick something in the middle. This is the moment when various contractors try to convince the client to use their services, presenting the full range of their capabilities, experience, and how they will translate the client’s budget into project benefits.
At this point – not in bad faith, I assume – it’s possible simply not to mention that they’re offering to build the system in a way that’s easier and cheaper today, but will block some possibilities for development in the future. When preparing a plan for system implementation, there are many elements that can be abandoned (and which the client doesn’t require). You can, for example, not write documentation, you can not write tests, you can hire inexperienced people to work on the project, who will learn on the fly.
These are all issues that need to be resolved in the long term. Even worse, the damage done by a junior developer can be irreversible – the system will work, but code which doesn’t comply with the standards will make it impossible for anyone to fix it, let alone develop it. In the near future, we will come up against the dilemma of whether to create a new system or continue to "put band-aids on a bullet wound".
During negotiations, hardly any vendor would dare to tell the client that, once created, software requires investment in system maintenance. Work whose results cannot be seen straight away. A cost that, when taken into account, drastically increases the price and lowers competitiveness. After all, offers are usually compared by people without technical knowledge (e.g. purchasing, marketing, development or innovation departments, etc.).
Looking to the future
To ensure its continuous operation, the IT system created – e.g. a website (e.g. WordPress), a web application (e.g. React, Symfony), or a store (e.g. Magento) – requires a server, a domain, and backups, among other things. The cost of these elements is usually well understood and accepted without batting an eye. However, this is not the whole story – we often miss something.
At the initial stages, when planning and creating the product, it’s easy to forget that after the website goes live, continuous work associated with maintaining the code and the environment will be needed. If the client is not informed of this in advance, they may be surprised by the additional cost in the future. No wonder that they then decide not to accept the cost; after all, it wasn’t planned in the budget.
It's very hard to spend money on changing something that still works. After all, everything works just fine, it’s been doing what it’s supposed to do for years – so why make any repairs, updates, or refactorings?
This applies equally to small websites. For example, websites built using WordPress can, to a certain extent, be configured so that updates happen automatically. However, it doesn’t change the fact that from time to time you have to check whether all the plug-ins are still working, whether the theme is being updated, perform major updates, and check that backups are working properly. These are activities that must be performed periodically, regardless of the complexity of the system. For smaller websites it’s just more noticeable – the cost of maintenance constitutes a higher percentage of the cost of building the entire website.
How can we overcome this impasse?
Approach software development in the same way as building a relationship. For software developers, this means: don’t kill the client with the project quote, don’t build a budget barrier, suggest an agile approach, use incremental product building. At the beginning, it’s also worth performing the analysis stage, which absolutely must be done in cooperation with the client – in partnership.
For the client, this means inclusion in the process, greater control over the product being created, spreading payments over time, and the possibility of more precise budget planning for subsequent years. With each successive month of cooperation, we get to know each other’s needs and capabilities better – this directly determines the amount of time spent and the pace of development.
Technical debt exists, has existed and will continue to exist – there’s nothing wrong with that. What’s missing is open communication with the client. A software company should act as a technical partner for the client; when negotiating the first contract, they should have conversations and plan cooperation for the long term, for many years to come.