Why Software Estimates Are Hard

Every quarter, someone asks me the same question in a slightly different costume. Sometimes it is a board member who wants a date for the new ledger...

Originally published onanselmfowel.com

Every quarter, someone asks me the same question in a slightly different costume. Sometimes it is a board member who wants a date for the new ledger reconciliation engine. Sometimes it is a product manager who needs to promise a launch to a partner bank. Sometimes it is an engineer, frustrated, asking why we even bother estimating at all when we are always wrong. The question underneath all of them is the same: why is it so hard to say how long software will take?

Why Software Estimates Are Hard
Why Software Estimates Are Hard

I have run engineering teams in regulated payments long enough to have made every estimation mistake worth making. I no longer believe estimates are hard because engineers are bad at math, or because managers are too optimistic, though both happen. They are hard because of what software actually is, and because of the organizational machinery wrapped around the work.

Building the Thing Is Understanding the Thing

The first uncomfortable truth is that writing software is not like building a warehouse from a finished blueprint. When you estimate a warehouse, the design exists before the first shovel hits the ground. The hard thinking is done; construction executes a known plan. Software is the opposite. The act of building is the act of figuring out what we are building. The code is the design, and we only finish designing it when we finish writing it.

This means an estimate is, at root, a prediction about how much we will learn and how fast. When my team scoped a new payout-routing service, the visible work looked like a few API endpoints and a database table. The actual work was discovering, three weeks in, that two of our partner banks defined a settled transaction differently, and that our reconciliation logic could not assume either definition. Nobody hid that complexity from us. It simply did not exist as a known fact until we started building and went looking.

So when someone asks for an estimate before the work begins, they are asking us to predict the cost of discoveries we have not yet made. We get better at this with experience, but we cannot eliminate it. The uncertainty is not a defect in our process. It is the nature of the material.

The Cone of Uncertainty Is Real

There is a well-worn idea in our field called the cone of uncertainty, and it deserves more respect than it usually gets. Early in a project, before any code exists, an honest estimate might be off by a factor of four in either direction. A task you call two weeks could genuinely be anywhere from a few days to two months. As you build, learn, and remove unknowns, that cone narrows. By the time you are halfway done, your estimate for the remaining work is usually quite good.

The problem is that the moment everyone most wants a precise number, the start, is exactly the moment the cone is widest. Business needs certainty up front to make commitments, sign contracts, and plan launches. Engineering can only offer certainty late, once the work has taught us what it is. This is a structural mismatch, not a failure of communication.

The most expensive estimates are the ones given with false confidence at the moment of maximum ignorance, then treated as promises for the rest of the project.

What I ask of my teams is to communicate the width of the cone, not just its center. A single number hides everything that matters. A range, paired with the specific unknowns that drive it, gives stakeholders something they can actually plan around. Saying four to ten weeks, with reconciliation edge cases as the main risk, is more useful than saying six weeks and pretending.

The Long Tail of Real Systems

When engineers estimate, they tend to imagine the happy path. The feature works, the data is clean, the dependency responds. That mental picture is honest, but it is a fraction of the actual work. The real cost of shipping in fintech lives in the long tail of everything that is not the happy path, and that tail is where estimates quietly die.

Consider a seemingly simple feature, letting a customer update their bank account on file. The core logic is trivial. The real work is everything around it:

  • Validating the account against the relevant bank verification service, and handling the cases where it times out or returns ambiguous results.
  • Deciding what happens to in-flight payments already routed to the old account.
  • Producing an audit trail that satisfies our compliance obligations and survives a regulator asking who changed what, when, and from where.
  • Adding fraud controls so a takeover attempt cannot silently redirect funds.
  • Migrating existing records and writing a rollback plan in case the change goes wrong in production.

None of these are optional in a regulated environment, and none of them appeared in the one-line ticket. Junior engineers estimate the tip. Senior engineers estimate the iceberg, which is one reason their numbers look pessimistic right up until they look correct.

Dependencies You Do Not Control

Even a perfectly scoped piece of work rarely sits alone. It depends on other teams, third-party services, partner banks, internal platform changes, and security reviews. Every one of those dependencies has its own queue, its own priorities, and its own cone of uncertainty. When you estimate your work, you are implicitly estimating theirs too, usually without their input.

I have watched a two-week integration stretch to two months because a partner's sandbox behaved differently from production, and the only person who understood the discrepancy was on leave. That delay had nothing to do with our code quality. It was a dependency we could see but not control. In payments this is the norm, because we sit in the middle of a network of institutions that move at their own pace and answer to their own regulators.

The practical lesson is to estimate dependencies separately and explicitly, treating any external party as a source of variance rather than a fixed input. When I review a plan now, I ask which dependencies are on the critical path and what our fallback is if each one slips. That conversation surfaces risk a single combined number would have buried.

The Unit Problem: Time Versus Complexity

A surprising amount of estimation pain comes from confusing two different questions. The first is how complex is this work. The second is how long will it take in calendar time. These are related but they are not the same, and conflating them causes endless grief.

Complexity is a property of the work itself and is reasonably stable. A given task has a certain inherent difficulty regardless of who does it or when. Calendar time, on the other hand, depends on who is available, how many meetings they have, whether they are interrupted by an incident, how much context-switching the week demands, and how many other commitments compete for the same hours. A two-day task by complexity can easily take two weeks of calendar time once the realities of a working team are applied.

This is why estimating in abstract complexity and then separately modeling throughput tends to work better than estimating in raw hours. It lets the team reason about the difficulty of the work without pretending to know the future state of everyone's calendar. The translation from complexity to calendar time is a separate, organizational question, and treating it as one keeps the two kinds of uncertainty from contaminating each other.

The Incentive to Be Wrong

Estimation does not happen in a neutral vacuum. It happens inside an organization with pressures, and those pressures push estimates in predictable directions. If past estimates were treated as deadlines and missing them brought criticism, engineers learn to pad. If padding gets challenged as sandbagging, they learn to give optimistic numbers to avoid the argument. Either way, the estimate stops describing the work and starts describing the politics.

I have seen talented teams produce systematically useless estimates because the culture punished honesty. When a high estimate triggers an interrogation and a low one earns praise, you are training people to lie to you, slowly and with the best intentions. The number you get back tells you more about how safe people feel than about how long the work will take.

If you want accurate estimates, you have to make it safe to give an accurate estimate, including the inconvenient ones. An estimate punished is an estimate corrupted.

As a CTO, the most useful thing I can do for estimation quality is rarely a process change. It is to react calmly when an honest estimate is larger than I hoped, and to never reward optimism that later proves false. Estimates are a measurement instrument, and you cannot get clean readings from one people are afraid to read accurately.

Why It Feels Worse in Regulated Fintech

Every domain has estimation difficulty, but regulated financial software carries a particular weight. The cost of being wrong is asymmetric. A consumer app that ships a rough feature can iterate next week. We cannot mishandle funds, leak account data, or fail an audit and simply patch it later. That asymmetry means a large share of our effort goes into correctness, reversibility, and provability, and that effort is genuinely hard to estimate because it is hard to see.

Compliance requirements also have a way of arriving mid-project. A regulator issues new guidance, a partner bank updates its requirements, or our own risk team raises a concern that reshapes the design. These are not scope creep in the lazy sense. They are legitimate, sometimes mandatory, and they land on timelines set before anyone knew they were coming. I budget explicitly for this now, treating regulatory variance as a line item rather than pretending the rules will hold still. The discipline this forces also makes us better estimators over time, because we learn, sometimes painfully, where the icebergs sit.

What Actually Helps

I do not want to leave the impression that estimation is hopeless. It is hard, not impossible, and a handful of practices reliably move the needle. None of them are clever. They are mostly about being honest with ourselves regarding what we do and do not know.

The single most effective practice is to break work down until the pieces are small enough to reason about concretely. A task you can hold in your head is one you can estimate; a quarter-long initiative is not. Decomposition does not remove uncertainty, but it exposes it, and exposed uncertainty can be managed instead of discovered at the worst moment. Alongside that, I lean on a few habits:

  • Track actuals against estimates without blame, so the team builds a real sense of its own throughput rather than guessing.
  • Re-estimate as the cone narrows, and update commitments accordingly, rather than treating the first number as sacred.
  • Reserve explicit buffer for the work we know we cannot see yet, and name it as such instead of hiding it inside individual tasks.
  • Separate the estimate from the commitment, so the business decision about what to promise is made consciously, with the uncertainty visible.

Over time, a team that does this develops something better than accurate single estimates. It develops calibrated judgment, an earned sense of how wrong it tends to be and in which direction. That calibration, more than any technique, lets me give a board member a number I am willing to stand behind.

Conclusion

Software estimates are hard because building software is an act of discovery, because the most precise numbers are demanded at the moment of greatest ignorance, because the real work hides in the long tail of correctness and dependencies, and because the organization around us quietly shapes the numbers we report. None of that goes away with a better tool or a stricter process. The honest path is to treat estimates as ranges built on stated assumptions, to make it safe to be accurate, to keep re-estimating as we learn, and to separate what we predict from what we promise. Do that consistently, and estimates become what they were always meant to be: a shared, evolving model of work we do not yet fully understand, held with humility and improved every time we are wrong.

Chat with us