Dev.to WebDev ๐Ÿ›  Dev ๐Ÿ‘ 0 ๐Ÿ“– 7 min read

Software Project Estimation: Scoping Quotes That Hold Up

Most software quotes are wrong for the same reason: they estimate the screens in the brief and ignore everything around them. Authentication, roles, audit trails, data migration, environments, monitoring and the admin pa

Software Project Estimation: Scoping Quotes That Hold Up

Most software quotes are wrong for the same reason: they estimate the screens in the brief and ignore everything around them. Authentication, roles, audit trails, data migration, environments, monitoring and the admin panel nobody mentioned can be as large as the visible features. When two vendors quote wildly different prices for the same brief, the gap is usually not skill or greed. It is which of those invisible items each quote includes.

I have estimated and delivered Laravel, Vue, Nuxt, Node and .NET systems for nine years, and at Loop Origin scoping is the step I refuse to rush. My method: a work breakdown that surfaces hidden scope, three-point estimates, a contract model chosen by uncertainty, and change control after kickoff.

How do you estimate a custom software project accurately?

Direct answer: Break the product into features and non-functional work, estimate each item as optimistic, likely and pessimistic hours, and combine them with a three-point (PERT) formula to get a range, not a single number. Price fixed-scope phases only where uncertainty is low, use time-and-materials for discovery and unknowns, and manage every later change through a written change request.

Why single-number estimates fail

A single number hides the uncertainty the client most needs to see. "Payment integration: 40 hours" might mean 24 hours with a well-documented gateway, or 90 with a regional provider whose webhooks are inconsistent. I have seen both.

The other failure is anchoring: once a figure is said in a sales call, everyone remembers it and nobody remembers the assumptions. Writing assumptions next to every line is the cheapest risk control in software.

Step 1: A work breakdown that includes the invisible work

I split every project into four layers before estimating anything:

Layer Typical items Often missing from quotes? Why it matters
Product features Screens, workflows, reports, notifications Rarely This is what the brief describes
Platform foundations Auth, roles and permissions, audit log, file storage, email, settings, admin panel Often Every feature depends on them
Data and integration Migration from the old system, imports, third-party APIs, webhooks Very often Legacy data is never as clean as promised
Delivery and operations Environments, CI/CD, backups, monitoring, security review, documentation, UAT support Very often The difference between "works on my machine" and "in production"

The second, third and fourth layers are where cheap quotes save money on paper. For a deeper look at how foundations change the build-versus-buy decision, see my DEV article on custom software vs off-the-shelf SaaS and three-year ROI.

Step 2: Three-point estimates per item

For each work item I record three figures in hours: optimistic (O), most likely (M) and pessimistic (P). PERT combines them:

  • Expected = (O + 4M + P) / 6
  • Standard deviation per item = (P - O) / 6

Here is a small extract from an illustrative B2B ordering portal. The hours are an example to show the method, not a benchmark for your project.

Work item O M P Expected Main assumption
Customer login, roles, password reset 16 24 40 25.3 Email and password only, no SSO
Product catalogue with price tiers 24 40 72 42.7 Up to three price tiers per customer group
Cart and order submission 24 36 60 38.0 No online payment in phase 1
ERP order export (CSV to SFTP) 12 20 48 23.3 ERP accepts a documented CSV format
Admin panel (customers, orders, products) 32 48 80 50.7 Standard CRUD and filters
Data migration from spreadsheets 16 32 80 37.3 Fewer than 20,000 rows, one cleanup pass
Environments, CI/CD, backups, monitoring 16 24 40 25.3 Single VPS plus managed database

Notice which rows have the widest spread: migration and ERP export. Those are where I spend discovery time before committing to a fixed price.

The summation is simple enough to keep in a script next to the estimate sheet:

import math

items = [  # (name, optimistic, likely, pessimistic)
    ("auth_roles", 16, 24, 40), ("catalogue", 24, 40, 72),
    ("cart_orders", 24, 36, 60), ("erp_export", 12, 20, 48),
    ("admin", 32, 48, 80), ("migration", 16, 32, 80), ("ops", 16, 24, 40),
]
expected = sum((o + 4*m + p) / 6 for _, o, m, p in items)
sigma = math.sqrt(sum(((p - o) / 6) ** 2 for _, o, _, p in items))
print(f"expected {expected:.0f} h, one sigma above: {expected + sigma:.0f} h")
# expected 243 h, one sigma above: 261 h

Summing variances assumes items are independent, which they are not entirely, so I treat the one-sigma figure as a floor for contingency, not a ceiling. I also add project management and QA as explicit lines rather than hiding them in feature hours.

Step 3: Choose the contract model by uncertainty, not by habit

Model Who carries the risk Works best when Watch out for
Fixed price for the whole project Vendor, priced in as a buffer Scope is small, stable and fully specified Inflated buffers, or a vendor cutting corners to protect margin
Time-and-materials (hourly or daily) Client Discovery, R&D, unclear integrations Needs weekly visibility and a budget cap
Fixed-price milestones after paid discovery Shared Most custom business applications Requires discipline on change requests
Monthly retainer for a dedicated team Shared, measured in velocity Ongoing product development Needs a product owner who prioritizes every week

My default for a new business application is short paid discovery under time-and-materials, then fixed-price milestones for well-understood phases. Discovery turns the widest estimates into known work, and the client owns the output. Our pricing page explains how we structure these engagements.

Wooden blocks stacked into a staircase, representing milestone-based software delivery

Step 4: Write a scope document a stranger could price

The test I use: could a different competent team produce a similar estimate from this document alone? If not, it is not a scope, it is a wish list. Each feature gets:

  • User story and acceptance criteria, written so a tester can say pass or fail.
  • Explicit exclusions. "No SSO", "No multi-currency", "No mobile app" save more arguments than any other sentence.
  • Non-functional requirements with numbers where possible: expected users, data volume, browsers supported, uptime target, data retention.
  • Dependencies on the client: content, API credentials, sample data, a decision-maker available within two working days.

Multi-tenant products need extra care here, because tenancy decisions ripple through every table. I covered those trade-offs in Multi-Tenant SaaS Database Architecture in 2026.

Step 5: Change control that does not poison the relationship

Scope will change; good products learn from users. The goal is that every change is priced before it is built. My change request template:

change_request:
  id: CR-014
  requested_by: Operations lead
  description: Allow customers to save repeat orders as templates
  reason: Top request from pilot customers in UAT
  estimate_hours: { optimistic: 10, likely: 16, pessimistic: 28 }
  impact: "+1 week on Milestone 3; no change to Milestone 2"
  decision: pending   # approved | deferred-to-phase-2 | rejected

Two rules keep this healthy. First, small changes can be swapped against equal-sized items in the backlog instead of adding cost, which keeps goodwill. Second, nothing is built until the decision field says approved, in writing.

Production failure modes I see in estimates

  • "Simple" data migration. Legacy exports with duplicate customers, free-text dates and missing foreign keys. Budget a cleanup pass and a dry run. My strangler-fig migration guide covers running old and new systems side by side.
  • Third-party APIs estimated from marketing pages. Always check for a sandbox, rate limits and webhook documentation before quoting.
  • No UAT window. Clients need time to test with real data; plan one to two weeks per major milestone.
  • Reporting added at the end. Reports often need data structures that should have been designed in month one.
  • One person holds all the knowledge. Estimate handover and documentation explicitly.

The scoping checklist

  1. List features, then add the foundations, data and operations layers.
  2. Estimate every item as optimistic, likely and pessimistic hours with written assumptions.
  3. Run paid discovery on the items with the widest spread.
  4. Choose the contract model per phase based on remaining uncertainty.
  5. Write acceptance criteria and explicit exclusions for every feature.
  6. Agree client dependencies and decision turnaround times.
  7. Adopt a change request template before kickoff, not after the first dispute.
  8. Re-estimate at every milestone using actual hours from the previous one.

If you are preparing a brief and want it reviewed against this checklist, our custom web application development team starts every engagement this way.

Frequently asked questions

Why do software quotes for the same brief vary so much?

Because the brief rarely defines foundations, data migration, integrations or operations. One vendor prices them, another assumes they are out of scope or will be handled later. Ask every vendor for a line-item breakdown with assumptions and exclusions, then compare like for like.

Is fixed price safer for the client?

Only when scope is genuinely stable. Fixed price moves risk to the vendor, who prices it in as a buffer or protects margin by cutting quality. For uncertain work, a capped time-and-materials phase is often more transparent.

How much contingency should a software budget include?

There is no universal percentage. Derive it from your estimate spread: the wider the gap between likely and pessimistic hours on key items, the larger the contingency. Items such as migration and third-party integrations usually drive most of it.

What is a paid discovery phase?

A short, fixed or capped engagement to clarify requirements, prototype risky parts and produce a scope document with estimates. It reduces the biggest unknowns before you commit to the full build, and you keep the output.

How do I stop scope creep without blocking good ideas?

Route every change through a written change request with an estimate and impact on milestones. Allow swaps of equal-sized items, defer the rest to a later phase, and build nothing that has not been approved in writing.

Should maintenance be included in the initial quote?

It should be quoted separately but discussed upfront. Hosting, security updates, dependency upgrades and small fixes continue after launch, and knowing that cost early avoids surprises in the first year.

Follow & Connect

๐Ÿ“ฐ Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes โ€” full credit and traffic to the original publisher.