Late projects are often honest estimates ignored. When you look back at why software ships behind schedule, you rarely find it was because the estimate was somehow impossible to predict. More often, an estimate existed, was understood to be conservative, and then got squeezed or ignored under business pressure. Estimating software work honestly means building estimates that your team and stakeholders can actually trust—and then defending them when they matter.
Over my 5+ years building production platforms, I've learned that estimation failures aren't usually math problems. They're communication problems. A developer estimates five days, thinks that's ambitious, but never says so out loud. A manager hears five days and commits to Friday. By Wednesday, we're all pretending the estimate was wrong instead of admitting it was never believed in the first place.
The shift happens when you stop treating estimates as predictions and start treating them as promises. That means doing the work to make them honest.
Break it down — Split work until each piece is under a day
The single best way to improve estimation accuracy is to break work into smaller pieces. Not because small estimates are somehow more accurate than large ones, but because small pieces force you to think concretely.
When someone says "build the user dashboard," that's an estimate waiting to fail. You don't know if they mean a skeleton layout or a fully animated, real-time data dashboard. You don't know if the backend is done. You don't know if design is locked. A week? Two weeks? Five days? All of these could be "right" depending on what's actually being built.
Instead, split it down:
- Design review and approval (1–2 days)
- API contract finalization with backend team (0.5 days)
- Fetch user profile and render in layout (1 day)
- Implement activity feed with pagination (1.5 days)
- Add charts using charting library (1 day)
- Unit and integration tests (1 day)
- Performance review and optimization (0.5 days)
- Code review and deployment (0.5 days)
Now each piece is concrete. You're not guessing about a dashboard anymore. You're estimating the actual work: pull data from this API, render this component, test this behavior. Each task should be small enough that you can defend it in five minutes of conversation.
I've found that a useful rule is: if you can't explain what "done" looks like in a sentence or two, break it down more. If you can't finish it in a day (even with a good day), break it down more.
Account for the unseen — Integration, testing, reviews and deployment take real time
This is where most estimates break down. A developer estimates the feature work—writing the code that makes the feature work—and forgets to add the time that the feature must actually survive in the real world.
I spent the better part of two years building an e-commerce platform before I stopped making this mistake. The happy path—"fetch products and display them"—takes a day. But what about:
- Tests failing because the test database isn't set up the same way as production
- The code review coming back with "we need to handle the null case here" on Thursday
- Waiting for another team's API to be ready for integration
- Load testing showing the query is too slow
- A deployment that fails because a migration didn't run
- A production incident at 11 PM because the feature works differently under load
None of these are emergencies or failures. They're the normal friction of software development. Yet most estimates pretend they don't exist.
Here's a concrete example from a recent feature. We were building a trading notification system using Kafka. The feature itself—consuming a message and storing it—was straightforward. But the estimate had to include:
- Setting up a local Kafka instance for development
- Learning the team's message schema (we had to ask why certain fields existed)
- Handling the case where a message arrives out of order
- Testing with production-like data volumes
- Coordinating with the platform team on deployment timing
- Observability setup (logs, metrics, alerts)
The core feature was maybe a day. The surrounding work was another two days. An estimate of "one day" would have been dramatically wrong.
When you break down your work, add a "non-feature" task explicitly. Call it "integration, testing, deployment, and review." Give it a realistic number. If your feature work is three days, this task is often another one to two days. It depends on how much is already in place, how many teams need to coordinate, and how much operational work the feature requires.
Give ranges — 'Three to five days' is more honest than 'four days'
I learned this lesson the hard way. A stakeholder asked "how long will the CRM dashboard take?" I said "four days." They heard a commitment. Four calendar days later, the work wasn't done. They were frustrated. I felt like I'd failed.
But I hadn't failed at estimation. I'd failed at communication. There was never a four-day estimate. There was a central guess with uncertainty I hadn't named. It could be three days if we're lucky and the API is fast. It could be six days if we discover edge cases or performance issues.
Ranges are more honest because they acknowledge what you actually know. You don't know if that API call will be 100ms or 1000ms until you try. You don't know if the design will need minor tweaks or a rethink. You don't know if the code review will be smooth or uncover a fundamental issue.
Instead of:
"The feature will take five days."
Say:
"I estimate three to five days. That's assuming the API is ready and we don't hit any performance issues. If either of those is uncertain, we should add another day or two to the range."
The second statement is more words, but it's far more useful. A manager can hear "three to five days" and plan around it. They can say "do you think it's more likely to be three or five?" and you can have a real conversation. Most importantly, if it takes six days because the API wasn't ready, nobody is surprised. You named that as a risk.
In practice, I use confidence levels. Low confidence (lots of unknowns) = 50% range. Medium confidence (some unknowns) = 30% range. High confidence (mostly known) = 20% range. So:
- High confidence: 4–5 days
- Medium confidence: 3–5 days
- Low confidence: 2–6 days
This isn't magical. But it keeps me honest and helps stakeholders understand what I'm confident about.
Surface risks early — Unknowns belong in the estimate, not in the excuse
The worst estimates I've given came from pretending I knew things I didn't. "I'll just figure it out as I go." That always costs time. The question is whether you own that cost or blame it on the work later.
Good estimation means identifying the risks upfront and putting them into the estimate.
When I was building a ride-hailing platform, we needed to integrate with a third-party payment provider. I could have estimated "integrate payments: three days." But I knew there were risks:
- Their API documentation was outdated (historical risk)
- We'd never done PCI compliance before (unknown complexity)
- We needed to handle payment failures, retries, and reconciliation (feature scope uncertainty)
- Their sandbox was separate from production (integration risk)
So the estimate was: two days for happy path, plus two days for the unknowns. "Four to six days, depending on how quickly we get sandbox access and whether compliance review surfaces new requirements."
That's not padding. That's honesty. It took five days. Nobody was surprised.
Here's how to surface risks:
- List the assumptions in your estimate. "This assumes the backend API is ready" or "This assumes we can use the existing authentication library."
- For each assumption, ask: what if this is wrong? How much time would that cost?
- If the cost is high and the risk is real, add it to the estimate explicitly.
You might end up with an estimate like this:
Feature core: 3 days. Dependencies (backend API, design approval): +1 day if either is delayed. Unknown complexity in matching algorithm: +1 day. Testing and performance review: +1 day. Best case: 5 days. Likely case: 6 days. Risky case: 7 days.
That's a longer conversation than "six days," but it's the estimate. You're not making up a number and hoping for the best. You're naming what you know and don't know.
Common mistakes
Confusing best-case with realistic-case: When people ask "how long will this take?" they usually mean "how long if everything goes well?" You usually mean "how long realistically?" You need to sync on that. If you're giving the realistic estimate and they're hearing the best case, you'll always be late.
Leaving estimates unsigned: An estimate without a name isn't an estimate. It's a guess. When you write down or say out loud an estimate, you're signing it. That changes how much care you take. Use that. Write it down. Say it in a meeting. Make it real.
Forgetting to update estimates as you learn: After a day of work, you know more than you did at the start. If you discover that the third-party API is slower than expected, you might need to re-estimate. That's not a failure. That's data. Use it.
Treating estimates as targets: An estimate isn't a goal to hit. If you estimated five days and you're done in three, that's great. If you estimated five and it takes seven, that means your estimate was useful—it caught reality that a faster guess would have missed. Don't blame yourself for being wrong. Blame yourself for not being honest about the uncertainty.
Key takeaways
- Break work into pieces small enough to explain and defend. If you can't finish a task in a day, it's probably more than one task.
- Account for integration, testing, reviews, and deployment explicitly. These aren't overhead. They're part of the work.
- Use ranges instead of single numbers. "Three to five days" is more honest than "four days" and easier to plan around.
- Name your assumptions and risks. The estimate should include time for things you don't know, not excuses for why you didn't account for them.
- Sign your estimate. Write it down. Say it in a meeting. Make it something you and your team can point to later and learn from.
- Update your estimates as you learn. The best estimate is the one based on real data, not the one you made on Monday before you started the work.






Comments
Loading comments…