The concept of "technical debt" has become a popular metaphor in software development in recent years. The idea boils down to the fact that the quality or maintainability of a codebase decreases over time, and you need to spend time refactoring or updating to keep the "debt" at a manageable level.
The "debt" part of the metaphor came about because it can be entirely reasonable to write low quality code (take out a loan) to accomplish short term goals. You then need to refactor (pay down the debt) at a later time. This happens often in software development processes that have sprints or milestones with fixed schedules and fixed deliverables. In order to complete the sprint, you do whatever needs to be done, then at the beginning of the next sprint you schedule time for refactoring.
Technical debt is not always a conscious choice however. Low quality code (e.g. buggy, hard to maintain, hard to read) will likely increase project costs in the future. You might think that a project with only AAA Gold Rated Super Star developers won't ever have technical debt (other than consciously chosen short term debt), but that's actually not the case. There are two other sources of debt which are for the most part inevitable—bit rot and a growing codebase.
Bit rot is actually caused by inaction. A codebase can "age" and become lower quality, even when it hasn't changed at all. This is caused because the environment where the program operates has changed. What were once completely correct technical decisions are now dated legacy issues. Some examples from my own work experience:
The other cause of technical debt is simple growth of the project. In any long (multi-year) project, you inevitably end up with some code that is a far cry from ideal. This can happen as requirements change. If you build features A, B and C months (or years) apart, you may end up with different code (and less reuse) then if you had built them all at the same time with the same mindset.
If debt is inevitable, how should you deal with it? If you are aware of the debt, then postponing dealing with it could be a viable strategy. We had one project that was developed more than 10 years ago on ASP.Net 1.0 Web Forms with no AJAX (because it didn't exist) and an obsolete data access technology (which was state of the art at the time). The project was finished and needed no further development. The application was just moved to a new server every 3-5 years. Then Windows Server 20 came along and the .Net Framework 1.0 was no longer supported. So we undertook a 10 hour project to update the framework (targeted the latest framework and fixed some obsolescence issues) and test against a newer version of the database engine. Ignoring the debt was the absolute right strategy here because the project wasn't under active development.
On the flip side, I have another Web application project of similar vintage that is under constant development. On that one we have a curious case of ancient code (from .Net 1.0) in the same codebase as state of the art. It's got a mix of WebForms and MVC, new and old database access, AJAX with client side frameworks and event driven full page post backs. Here the technical debt is known, and we have varying strategies for dealing with it. On the one side is pure pragmatism. I strongly believe that there is no difference between low quality code that works and perfect quality code that works, until you touch it. So for the dusty corners of the application where requirements don't change and nothing breaks, we leave it alone. For new development we incorporate new technologies and techniques as they make sense, acknowledging that each new "thing" must fully justify the added complexity it brings to the project. When we are required to touch old code, I tend to make a short refactoring and cleanup pass before I add new features.
On other projects under development the best strategy is simply to refactor continuously. Do small cleanups all the time, and make sure to schedule time for bigger refactoring periodically as needed.