Blog #39: The 'Will Fix Later' Promise and the Compound Interest of Technical Debt
The story of 'temporary' code written under deadline pressure and how it returned to attack the system at the most critical moment.
1. The Context
The biggest sales campaign of the year (Black Friday) was only 3 days away. The checkout page interface suddenly glitched: "Unable to calculate taxes for customers in certain geographic regions." I opened the price calculation logic file, and immediately hitting me was a comment I had written myself... 2 years ago:
// TODO: @ivan - Refactor this hardcoded logic after integrating the new tax API. Rushing for launch.
At that moment, I froze. My heart skipped a beat. That "Will fix later" from 2 years ago was now a "fuse" threatening the operation of the entire business on its most important day. I felt guilty and profoundly regretful. The pressure now wasn't just to fix the bug, but to face my own past procrastination.
2. Foundational Knowledge
Technical Debt is a familiar concept. It's like borrowing money. You choose the fast way (borrowing money) to achieve a short-term goal (buying something immediately). But all money comes with interest. The "interest" on technical debt is the difficulty in maintenance, slower development speed, and increased risk of system collapse.
The problem isn't that you're not allowed to "borrow." The problem is you must manage it. If you keep borrowing without a plan to pay it back, eventually, the "interest" will consume all your effort.
3. The Specific Problem
Two years ago, when integrating the tax system, the partner's API wasn't ready. To make the launch day, I wrote a "temporary" function by hardcoding geographic region codes into the Frontend.
// The "temporary" source code that survived for 2 years
const calculateTax = (regionCode, amount) => {
if (regionCode === 'SG' || regionCode === 'HN') {
return amount * 0.1; // 10% VAT
}
// TODO: @ivan - temporary placeholder, call Tax Service API later
return 0;
};
The system then only had a few hundred users. But 2 years later, the company had expanded to 64 provinces and international markets. That "temporary" function had silently caused financial loss for the company for a long time by miscalculating taxes in other regions.
4. How I Handled It
I had to drop everything else to focus on "paying the debt."
My initial solution was to continue "patching"—adding dozens of if/else checks to the old function for Black Friday. But I realized if I did that, I would be borrowing yet another loan at an even higher interest rate.
I decided to use the next 24 hours to do the right thing:
- Call the API directly from the Backend for tax calculation.
- Write an independent currency and tax utility suite with 100% Unit Test coverage for region codes.
I used Jest to simulate every Backend API failure case to ensure the Frontend never unilaterally decided tax rates again.
5. Trade-offs
Doing the "right" thing in a rush has a fatal drawback: Risk. Changing core logic right before a big day is extremely dangerous. We could have broken the entire checkout process if the new API had issues.
Comparison:
- The quick fix: Add 10
if/elsechecks. Takes 30 minutes. Low immediate risk, but high technical debt. - The sustainable fix: Integrate the new API. Takes 1 day. High immediate risk (due to the deadline), but completely eliminates the technical debt.
I chose the sustainable way and accepted staying at the office until 4 AM to monitor every possible risk.
6. Lesson Learned
I learned a lesson I'll never forget: There is no such thing as 'Temporary' in programming. Whatever is running will stay forever until it breaks.
- Advice: Never write a
TODOwithout a corresponding ticket in the backlog or a specific deadline to delete it. - Self-reflection: Was I over-engineering by trying to write polished tests in the heat of the moment? I doubted myself too. But after discovering that the new code caught 3 potential logical errors thanks to Unit Tests, I knew I had done the right thing.
Juniors are often excited because "a quick fix is done." But a true Senior is someone who worries about code that is "done and forgotten." If you must choose a fast way for a deadline, make sure you pay that debt back in the very next Sprint.
Notes on the price of procrastination in source code.
Series • Part 39 of 50