NNabeel Hassan

Blog · November 6, 2026 · 8 min read

How to Estimate a Software Project (and Why Estimates Go Wrong)

By Nabeel Hassan — AI Engineer · ICPC World Finalist

TL;DR: A software estimate goes wrong for predictable reasons: it is given as a single number, it is built from the parts you understand and ignores the parts you do not, and it leaves out the time that belongs to other people (app store review, carrier registration, a client's API access, a field test). The way I estimate now is to break the work into pieces small enough to picture, label each one as known, similar-to-something-I-have-done, or genuinely new, give a range instead of a number, run a short spike on anything new before committing, and list the external waits as their own line items. The range narrows as the unknowns get resolved, and I say so up front.

I have been asked "how long will this take?" more times than any other question in seven years of shipping software, first as a freelance Unity developer, then as a CTO for startups in the US and Italy, and now building AI voice agents and my own products. I have also been wrong about the answer, sometimes badly. This is the method I ended up with, mostly by learning which kinds of mistakes kept repeating.

Why software estimates go wrong

The usual explanation is that developers are optimistic. That is true but not very useful. The more specific problem is that estimates are built from the work you can see, and the expensive work is usually the work you cannot see yet.

When someone describes a feature, my brain fills in the familiar parts immediately. A login screen, a dashboard, a booking flow: I have built versions of all of these, so I can picture the work and size it. What I cannot picture is the part that is new for this specific project, and an estimate built only from what I can picture is quietly assuming the new part takes zero time.

There are three repeat offenders I now look for on purpose:

Step 1: Break the work down until you can picture each piece

An estimate for "build the app" is a guess. An estimate for "a screen that lists a player's past sessions, loads from the existing API, and handles the empty case" is something I can actually reason about.

I keep splitting until each piece is something I could describe in two or three sentences and imagine doing in a day or two. If a piece still feels foggy at that size, the fog is the signal: it means I do not understand it yet, and that piece needs a different treatment from the rest.

This is also where a good brief saves real money. A client who has written down what the product must do, who it is for, and what success looks like (the things I cover in how to write a software project brief) gets a tighter estimate, because there are fewer pieces I have to guess at.

Step 2: Label each piece known, similar, or new

Once the work is in pieces, I tag every one of them:

The labels matter more than the hours. A project that is 90 percent known and 10 percent new is a very different commitment from one that is half new, even if both add up to the same total on paper.

Step 3: Give a range, not a number

A single number communicates a certainty nobody has. I give a range for every piece and for the total: a realistic low if things go the way they usually do, and a realistic high if the unknowns bite.

For known pieces, the range is narrow. For new pieces, it is wide, and that width is honest information for the client. It tells them where the risk sits. When a client sees that most of the spread in an estimate comes from one integration, they can make a real decision: fund a quick investigation first, simplify that feature, or push it to a later phase. That conversation is the same one I describe in what to cut from an MVP, and a range is what makes it possible.

I also say how the range will change. Something like: "This is wide today because of the CRM integration. After the first week, once we have connected to it, I will give you a tighter number." Estimates are allowed to improve as you learn. What breaks trust is a number that silently drifts without anyone explaining why.

Step 4: Spike the unknowns before committing

For every piece tagged as new, I would rather spend a day or two finding out than a month being wrong. A spike is a short, throwaway piece of work whose only job is to answer a question: does this API actually return what the docs say? Can this headset run the scene at a usable frame rate? Does this voice platform let us transfer a call the way the client needs?

Spikes are cheap compared with what they prevent. When I was building and testing voice agents at Fortell AI, the fastest way to know whether an approach would hold up was to build a rough agent and call it, not to reason about it on paper. The same is true for most new technology. Ten minutes of real behaviour is worth more than an hour of reading.

The output of a spike is not code to keep. It is a better estimate, and sometimes a better plan. Occasionally the spike shows that the new piece is a much bigger job than anyone thought, and finding that out in week one is a gift compared with finding it out in week six.

Step 5: List the external waits as line items

This is the step most estimates skip, and it is where a lot of "late" projects actually lose their time. I write down every dependency on someone outside the team and give it its own entry with its own expected duration:

Putting these on the list does two things. It makes the estimate more accurate, and it makes it obvious which delays are not engineering delays, which avoids a lot of uncomfortable conversations later.

Step 6: Add the work everyone forgets

Before I hand over a number, I check the estimate against a list of things that are easy to leave out:

None of these are exciting, and all of them take time. Leaving them out does not make the project cheaper. It just moves the cost to a later, more awkward moment.

How I re-estimate during a project

An estimate is a starting point, not a promise carved in stone. On longer projects I revisit it at natural checkpoints: after the first spikes, after the first real integration, and before the final stretch. Each time, the unknowns are smaller, so the range gets narrower.

When the scope changes, I estimate the change on its own and say what it does to the timeline before starting it. That rule matters more than the pricing model you choose, and it applies whether the work is fixed price, hourly, or on a retainer. "Yes, we can add that, it adds roughly this much, do you want it in this phase or the next?" is a sentence that has saved more client relationships than any clever estimating formula.

The short version

Break the work down, label what is new, give ranges, spike the unknowns, list the external waits, and include the work everyone forgets. An estimate built that way is not guaranteed to be right. But when it is wrong, you will know why, and you will find out early enough to do something about it.


I scope and build software for founders across the US, UK and Europe, from AI voice agents to mobile apps, Unity and XR, and I have led engineering as a CTO for several startups. If you want an honest range for your project, with the unknowns named, more about me is here, or book a call.

FAQ

Why are software estimates usually wrong?

Because they are built from the parts of the work the developer can already picture, while the expensive parts are the ones nobody has done before: integrations with systems you do not control, time that belongs to other people such as app store review, and the edge cases that turn a demo into a product.

Should a software estimate be a single number or a range?

A range. A realistic low and high for each piece of work shows where the risk sits, and the range should narrow as unknowns get resolved through short spikes and early integration work.

What is a spike in software estimation?

A short, throwaway piece of work, usually a day or two, whose only job is to answer a question about something new, such as whether an API behaves as documented or a headset can run a scene fast enough. Its output is a better estimate, not code to keep.

What do software estimates most often leave out?

External waits such as app store review, carrier registration, API access and client feedback rounds, plus error and empty states, support for older app versions, deployment pipelines, testing and handover.

Building something in this space?

I take on AI-agent, automation and product work directly — scoped fast, shipped fast.

Book a discovery call →

Keep reading