← Our FailuresHardcode-and-cache is a 'very bad fix.' Honor the real parameter and wire the general path; fix the cause, not the symptom.
intermediate5 min read · updated 2026-06-20
Market & numbers — every figure sourced
prod_fix_cost_multiplier100 x vs design-phaseBlack Duck — Cost to Fix Bugs During Each SDLC Phase (citing IBM Systems Sciences Institute)
tech_debt_share_of_estate30 percent of technology estate value (midpoint of 20-40%)McKinsey — Tech debt: Reclaiming tech equity (survey of 50 CIOs, 2020)
new_product_budget_diverted15 percent of new-product tech budget (midpoint of 10-20%)McKinsey — Tech debt: Reclaiming tech equity
Hardcode-and-cache is a "very bad fix"
A user asked the assistant for the weather. It answered correctly. Ship it, right? Except the next user asked for a different city and got the same answer. And the next. Every query, regardless of the city in the request, returned the weather for one hardcoded location.
The "fix" that caused this was the kind that feels productive in the moment: the weather lookup was flaky, so someone pinned a known-good result and cached it. The symptom (a failing lookup) disappeared. The cause (a general path that didn't honor the input parameter) was never touched. The system now lied confidently to everyone who wasn't asking about that one city.
This is the archetype of a band-aid: it makes the red light turn green without making the underlying thing true.
What we tried
The flaky path was a weather query that sometimes failed or returned slow. The instinct was to make the failure stop:
- Hardcode a value that's known to work for the test case in front of us.
- Cache it so it stops re-failing.
- Watch the immediate error disappear and call it done.
The test in front of us passed. The demo worked. The general behavior was broken for every case we didn't personally type in.
What broke
A band-aid doesn't remove the failure — it relocates it to a place you're not looking and a time when it costs more to find.
- The bug got more expensive, not cheaper. A defect caught in design costs a fraction of one caught in production. Industry data popularized from the IBM Systems Sciences Institute puts a production fix at up to 100x the cost of fixing the same defect at design time. Pinning a value doesn't pay that bill — it defers it and adds interest.
- It became silent. A loud failure (the lookup errors out) is a gift: it tells you exactly where to look. A hardcoded-and-cached value fails silently — it returns a plausible wrong answer. Nobody gets an alert. You discover it when a customer does.
- It compounds into technical debt. McKinsey's CIO survey found tech debt amounts to roughly 30% of the value of an entire technology estate (the 20-40% range), with about 15% of the new-product budget diverted to servicing it (the 10-20% range). Every band-aid is a small loan against that estate, and the interest is paid by the next engineer who has to reverse-engineer why one city is special.
- It poisoned trust. A correct-looking answer that is actually wrong is worse than an obvious error, because users act on it. Faking generality is a special case of faking a result — and a tool that fabricates is worse than a tool that honestly says "I couldn't fetch that."
The fix
Honor the real parameter. Wire the general path. Fix the cause, not the symptom.
For the weather case that meant: take the city the user actually asked for, pass it through to the real general lookup, and fix that path's flakiness (retry, timeout, fallback to an honest "couldn't fetch") instead of pinning one answer. The repair is to make the general case true, not to make one specific case look true.
The diagnostic that gets you there is the Five Whys — keep asking "why" until you hit a systemic, fixable cause instead of a symptom you can paper over:
- Why is the weather wrong for this city? Because the value is hardcoded.
- Why is it hardcoded? Because the real lookup was flaky.
- Why was flaky lookup answered with a hardcode? Because we optimized to make the error stop, not to make the answer correct.
- Why did "make the error stop" win? Because the test only checked one city, so the symptom looked solved.
- Why did one-city coverage pass for "works"? Because we never asserted on the general path — the parameter was never honored. ← root cause.
Stop at "make the error stop" and you ship a lie. Push to the fifth why and you fix the system: honor the input, harden the real call, and add a test that varies the parameter so a future band-aid can't pass.
Apply it
- A green test is not a true result. Before you call a fix done, ask: did I make the general case true, or did I make one case look true? If your fix only works for the example in the ticket, it's a band-aid.
- Treat silent-correct-looking output as the worst failure mode. A fix that converts a loud error into a quiet wrong answer is a regression, not a repair. Prefer an honest empty state ("couldn't fetch") over a fabricated plausible one.
- Never hardcode a parameter the caller supplies. If a value comes in as input, it must flow through the logic. Pinning it is faking generality, and faking generality is faking a result.
- Run the Five Whys before you write the patch. If you can't articulate the systemic cause, you're about to treat a symptom. The cause is usually one or two layers below where the error surfaced.
- Write the test that varies the input. The band-aid survived because the test only checked one case. The permanent guard is an assertion that exercises the general path — different city, different account, different edge — so the next shortcut fails CI instead of failing a customer.
- Pay the small bill now. A design- or commit-time fix is up to 100x cheaper than the production version of the same defect. The band-aid feels faster today and is dramatically slower across the life of the codebase.