You’ve been there. A team gives you a timeline. You plan around it - a launch, a hire, an investor update, a client promise. Then the date arrives, and the work doesn’t. The explanations sound reasonable, maybe even familiar, but you’re left wondering whether you were misled, whether the team is any good, or whether this is just how software works.
Mostly, it’s the last one. Software estimates are almost always wrong, and understanding why will make you a far sharper judge of the people you hire to build things for you. This isn’t about bad developers. It’s about how estimation actually works, plus a little bit of psychology that affects everyone who has ever guessed how long something will take.
Coding is partly a craft, and you can’t put a precise number on craft. But an experienced team always knows the floor, the ceiling, and where the surprises tend to hide.
The core problem: people estimate the best case
When you ask a developer how long something will take, their mind does something very natural. It pictures the clean path - the major steps, the obvious dependencies - and adds up the time for those pieces. What it quietly leaves out is everything that isn’t the happy path: code review, testing, the bug found late on a Friday, the quality bar that turns “done” into “actually done,” the three other things already on that person’s plate.
Psychologists Daniel Kahneman and Amos Tversky gave this a name in 1979: the planning fallacy, our tendency to underestimate how long our own tasks will take even when we know similar tasks have run long before. It’s not lying. It’s optimism baked into how the brain forecasts its own work - and it’s stubborn enough to show up even among people who know about it and are actively trying to correct for it. Good teams know this about themselves. That self-awareness is the first thing worth looking for.
Estimates become commitments far too early
Here’s the trap. The moment a number leaves someone’s mouth, it stops being an estimate and starts being a deadline. “Probably about three weeks” gets written down, repeated in a meeting, and quietly hardens into “due in three weeks” - same number, very different promise.
Business pressure makes this worse, even when the pressure is well-meaning. Nobody likes being the person who says a project will cost more or take longer. Everybody likes to be liked, and no one wants to be the team that keeps raising the price. So developers often say “yes, we can do that” when the honest answer is “let me think about that and come back to you.”
And here’s the part that’s easy to misread. A developer who fires off a barrage of questions, or who says “I need to sit with this and get back to you,” can come across as unsure - even a little incompetent. It’s usually the reverse. The ones asking the most questions are often the ones who’ve been burned before and know exactly where projects tend to go sideways. A team that hands you a confident number on the spot, before they’ve understood the problem, isn’t being decisive. It’s guessing, and telling you what you want to hear.
Complexity doesn’t scale in a straight line
It’s tempting to assume that a feature twice as big takes twice as long. It rarely works that way. Some of the simplest-sounding features sit at the foundation, and everything else gets built on top of them.
The structure of the core database, for example, quietly decides both how hard the rest of the build will be and how fast the finished product feels to your users. The underlying framework can make or break the experience, and sometimes a particular integration simply doesn’t play well with the framework a team has chosen. Those early decisions demand real critical thinking, and when they need to be revisited later, the delays are rarely small.
Integrations add their own brand of risk. I once worked on a product that pulled app data from the Google Play and Apple App stores through a third-party API. One day the provider changed that API’s structure with no warning. Because the product talked to it directly, it broke in production the moment the change went live. The real fix wasn’t just reconnecting the pipe - it was rearchitecting so the data was stored locally, synced on a schedule, and monitored, so that the owners and the developers got alerted the instant something looked off. A single change on someone else’s system can break your product, and building in that kind of protection takes work that almost never appears in the first estimate.
Then there’s the ending. The last stretch of a project is famous for swallowing time. Take a corporate website we built for a large multinational in the hospitality industry - visually rich, full of animation. It looked finished long before it actually was. QA surfaced a wall of problems that hadn’t been obvious during the build: poor Core Web Vitals scores and a string of accessibility gaps. Getting those scores into the green and reaching full WCAG 2.2 AA compliance - while keeping the animations crisp and wrestling with both server and client caching - turned into slow, exacting work. The finishing touches are each small, but there are too many of them, quality assurance takes longer than anyone expects, and a single fix can trigger a fresh round of testing across every connected part of the system. A Bell Labs engineer named Tom Cargill summed it up decades ago, and it has stuck around because it keeps being true:
“The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.”
Add multiple people working on different modules at once and you introduce yet another layer: code that conflicts, small miscommunications, and the ordinary friction of humans coordinating. None of this means a team is incompetent. It means software is genuinely hard to predict.
What good teams do differently
If estimates are this unreliable, how do you tell a strong team from a weak one? Not by who promises the soonest date. By how they handle uncertainty.
They give ranges, not single dates - and they explain why. A good team understands that crafting software is partly an art; everyone has a different way of reaching the same result, and bumps appear around corners no one could see. But experience lets them bound it. Based on their history with a given technology, they generally know the minimum time they’ll need and the amount that would be more than enough even if things go sideways. They also know that life happens - people get sick, urgent projects appear - and they leave room for it rather than pretending otherwise.
They separate the best case from the likely case from the safe commitment. An experienced architect or team lead can hold all three in their head at once, because they know the team, the technology, and your business needs well enough to tell them apart. The “best case” is what they’ll quietly hope for. The “safe commitment” is what they’ll actually promise you.
They use past projects as a reference, not gut feel. Say you want a new module added to an existing product. Even after reading through the current code, a seasoned architect knows curveballs are coming. On one ecommerce project, our task was to rebuild the analytics - strip out the old setup and create a clean module that fed events into the data layer exactly as the analytics specialist wanted. We were told the checkout module it all depended on worked flawlessly. It didn’t, quite: the data wasn’t structured consistently across different order and customer types, some values were missing entirely for certain orders, and sensitive customer information was being exposed in a public browser object. Making it clean and generic enough to support any kind of analytics, without breaking the live checkout, took a couple of weeks nobody had budgeted for. Experience teaches you to price that kind of surprise in.
They flag the unknowns early instead of absorbing them silently. Strong teams use experience and imagination to walk through how a feature will really be used, spot the things that could blow up the schedule, and ask for clarification before they start - or the moment they realize they need it. If a team can begin your project without asking a single question, that’s not confidence. That’s a red flag.
What this means for you as a decision maker
You don’t need to read code to judge a development team. You need to watch how they behave around estimates.
Red flag: a team that never pushes back on your timeline. If no one has ever told you a date is too aggressive, you’re unlikely to get the result you want on schedule. And if you somehow do, ask hard questions about quality - because the most common way to hit an unrealistic date is to cut corners in places you can’t see.
Green flag: a team that asks hard questions before estimating. When a team comes back with questions instead of an instant number, that’s the sound of due diligence. It means they’ve discussed the work, thought through the scenarios, and identified the things that affect both their effort and your quality. The best ones go further and suggest improvements that are cheap to include now and expensive to bolt on later.
Build a culture where honest estimates are rewarded, not punished. If an estimate strikes you as too high, or you decide not to proceed, say why. Give the feedback. Teams that get punished for honesty learn to stop being honest, and an optimistic number that makes you feel good today is worth far less than a realistic one that lets you plan.
The takeaway
Perfect estimates were never the goal. Honest, well-reasoned ones are - and they come from teams that treat estimation as an ongoing conversation rather than a single promise made under pressure. Encourage that conversation. Reward the pushback. The best technical partners aren’t the ones who tell you what you want to hear. They’re the ones who tell you what you need to know early enough to do something about it.