Thinkr

Craft

Why Engineers Can't Estimate Your Spec

Six ambiguities that make an estimate impossible, the question each produces, and why a wide range measures the document rather than the engineer.

Galang Aulia · 5 min read
Craft

When an engineer says they cannot estimate something, the usual reading is caution, or padding, or reluctance to commit. It is almost always simpler than that: the spec contains a decision nobody has made, and the size of the work depends on which way it goes.

An estimate is a claim about a known scope. Ask for one before the scope is known and you are not getting an estimate, you are getting a guess about your intent — which is why the number comes back wide, hedged, or not at all.

Here are the six ambiguities that produce that, and the question each one generates.

1 · Unbounded data

"How many are we talking about?"

A list of ten and a list of ten thousand are different features. One is a map over an array; the other is pagination, virtualisation, a query plan, and probably an index.

Nothing in "users can see their projects" says which. So the engineer either picks the cheap reading and gets it wrong at scale, or picks the expensive one and looks slow. Both are bad, and the spec caused both.

Collapses when you write: the expected volume, the ceiling, and what happens past it.

2 · Unnamed states

"What does it show when there's nothing there?"

Every screen has more states than the one you described. Empty, loading, partial, permission-denied, failed. Each is a design decision and a chunk of work, and a spec that names one state has silently delegated the other four.

The cost is rarely the code. It is that the engineer has to stop, ask, wait, and context-switch — or invent something, which becomes a design decision made by whoever was assigned the ticket.

Collapses when you write: every state the screen can occupy, with what appears in each.

3 · Undefined permissions

"Who can do this?"

Permission questions look small and are structurally large. "Admins can export the participant list" leaves open whether a non-admin sees a disabled button or nothing, whether the check happens in the UI or the API or both, and what a stale session does.

The gap between "hide a button" and "enforce authorisation at every layer" is days of work, and the sentence covers both.

Collapses when you write: who cannot, what they see, and where the rule is enforced.

4 · Unstated dependency behaviour

"What if it doesn't respond?"

Any spec that touches a third party — payment provider, model API, email service, an internal service owned by another team — has an implicit failure mode, and specs almost never state it.

Retry or fail? How many times? Does the user wait, or does the work queue? Is the operation idempotent, and if not, what stops a double charge? Each answer is a different amount of work, and "integrate with X" contains all of them.

Collapses when you write: the timeout, the retry policy, the user-visible behaviour on failure, and whether the operation can safely repeat.

5 · A rule with no owner

"Where does this number come from?"

Pricing, proration, scoring, ranking, eligibility. The spec displays a number; it does not define how the number is produced.

This is the most expensive ambiguity on the list, because the engineer cannot resolve it alone — it is a business rule, not a technical decision, and finding out means a conversation with someone who may not have decided yet. That is not estimable at all; it is blocked, wearing an estimate's clothing.

Collapses when you write: the calculation, its inputs, and its edge behaviour — rounding, zero, negative, currency.

6 · Silent performance expectations

"How fast does this need to be?"

Nobody writes "the report should be slow," so every report carries an unstated speed requirement. The engineer has to guess whether "reasonably quick" means a synchronous query, a cached view, or a background job with a notification when it finishes. Those are three different architectures.

Collapses when you write: a number and a condition. Non-functional requirements with no threshold read like requirements and behave like opinions.

The tell: a range wider than 3×

Engineers are reasonably good at sizing code they understand. When an estimate comes back as "three days, maybe three weeks," that spread is not uncertainty about implementation — it is the distance between two different features that are both still compatible with your document.

Treat a wide range as a diagnostic rather than a negotiation. The useful next question is not "can we tighten that?" but:

What would have to be true for it to be the three-day version?

The answer is a list of the decisions your spec left open, delivered for free by the person best placed to spot them.

When "it depends" is the correct answer

Sometimes the unknown is real: an unfamiliar library, a legacy system nobody has touched, a performance question that genuinely cannot be answered by reading code.

The honest response is a time-boxed spike — two days whose deliverable is an estimate, not a feature. That is a different thing from a number invented to end an uncomfortable meeting, and it is worth insisting on the distinction, because one of them tells you something and the other one tells you what you wanted to hear.

The reframe

An estimate is a measurement of two things: the work, and the document describing it. When the number is vague, it is worth asking which one you are actually measuring.

This is uncomfortable, and it is also the most useful feedback loop available to a PM. The engineer who cannot estimate your spec has just told you, precisely and for free, where the specification is incomplete — usually faster and more specifically than any review would have. The questions in this post are the review; they just arrive late, from someone who now has to wait on the answers.

It is also why the estimation conversation is worth treating as a shared artifact rather than a negotiation. Teams that write for the engineers reading it get narrower ranges, not because the engineers are more confident, but because there is less left to be confident about.

Getting them earlier is the entire argument for running a structured pass before handoff. Same questions, asked while they are still cheap.

FAQ

Why do engineers refuse to estimate? Because the spec contains a decision nobody made, and the size depends on which way it goes.

What does a wide range mean? An unresolved branch. Three days versus three weeks is the distance between two features your document still permits.

How do I get better estimates? Close the branches first — bound the data, name the states, state permissions, define failure, put numbers on performance.

What if it genuinely can't be estimated? Time-box a spike whose deliverable is an estimate. That is honest; an invented number is not.

New posts and release notes. No spam, unsubscribe anytime.

Stop shipping foggy PRDs.
Start the critique loop.

Three minutes to sign up. No credit card. Cancel by closing the tab.

Start freeSee pricing