Estimates Fail Because Teams Estimate the Wrong Thing
Most estimates describe how long the coding will take. Most overruns come from everything that surrounds the coding, which is exactly the part nobody put a number on.
Why software estimates miss so consistently, and how measuring implementation time while ignoring uncertainty, coordination, and integration produces predictable overruns.
Introduction
An engineer says a feature will take three days. Three weeks later it ships.
The usual explanations get offered — the estimate was optimistic, the scope grew, the engineer was inexperienced. Sometimes those are true.
More often the estimate was accurate about the thing it measured. It just measured the wrong thing.
This article is for teams whose estimates are consistently wrong in the same direction. Consistent bias is not a skill problem. It is a definition problem.
The Core Judgment: People Estimate Implementation and Get Judged on Delivery
When an engineer pictures a task, they picture writing the code. That mental simulation is often quite good. If the work were only implementation, three days would have been right.
But delivery includes the parts nobody simulated:
- understanding the existing code well enough to change it safely
- the ambiguity in the requirements that only surfaces mid-build
- review, revision, and the second review
- integration with a system that behaves differently than documented
- edge cases discovered while testing
- the deploy, and whatever the deploy reveals
None of that is overhead in the sense of waste. It is the job. It is just not what got estimated.
So the number is not too low because someone was careless. It is too low because it answered a narrower question than the one being asked.
How This Breaks in the Real World
The first consequence is that padding gets applied instead of understanding. Teams learn their estimates run short, so they multiply by two or three. Sometimes that works. Often it hides which parts were actually uncertain, so the same surprises recur with more slack around them.
The second consequence is that uncertainty gets flattened. “Three days” and “three days” mean very different things when one task is a well-understood change to code you wrote last month and the other requires integrating with a vendor API you have never called. Both get one number, and the number carries no information about which is which.
The third consequence is political. Once an estimate is spoken, it becomes a commitment in someone else’s plan. Revising it upward feels like failure, so the engineer absorbs the difference — by cutting tests, skipping the refactor the change deserved, or working late. The estimate holds and the codebase pays.
That last one is the expensive failure, because it is invisible in the delivery metrics and shows up months later as something else.
A Real Example: The Two-Day Integration
I watched a team estimate two days to add a third-party payment integration. The vendor had a client library and clear documentation. The code, in the end, was maybe two hundred lines.
It took nearly three weeks.
Almost none of that was writing the integration. It was getting sandbox credentials through a procurement process. Discovering that webhook delivery was at-least-once, which meant the handler needed to be idempotent, which meant a schema change. Finding that one error code in the docs did not match the actual behavior, and waiting on support. Then the reconciliation logic for payments that succeeded at the vendor and failed on our side — a case nobody had discussed because it did not exist in the happy path.
The two-day estimate for writing the integration was correct. The work was never two days of writing the integration.
What I Would Do Instead
I stopped asking “how long will this take” as the first question. It compresses too much into one number.
Instead I ask what we do not know yet. If the answer is “not much,” the estimate is probably reliable. If the answer includes a system we have not touched, a team we have not talked to, or a requirement still being debated, then the honest output is not a number — it is a plan to reduce the uncertainty first.
A few things that help in practice:
- estimate the unknowns separately from the known implementation work
- timebox investigation, then re-estimate with what you learned
- say the assumptions out loud, because that is where the miss usually lives
- treat a wide range as real information rather than as evasion
- distinguish “I have done this before” from “I understand how this would work”
That last distinction predicts overruns better than almost anything else I have seen.
And when an estimate turns out to be wrong, I want to know which category was wrong. Implementation taking longer than expected is one problem. Discovering three requirements mid-build is a completely different one, and only the second is likely to repeat.
Closing
Estimation gets treated as a forecasting skill that some engineers have and others lack.
Mostly it is a scoping problem. People give accurate answers to the question they heard, and the question they heard was about writing code, while the question being asked was about delivering a change into a system full of other people’s assumptions.
The number is rarely the problem.
What the number was counting usually is.