The biggest cost driver is rarely the technology stack — it is how much is still undecided. Each unanswered question in the requirements turns into padding inside the number you receive. A team that has no visibility into what happens on the unhappy path has to assume the worst. Putting two weeks into a proper discovery often reduces the overall figure much more than haggling over hourly rates.
Integrations remain another reliable source of cost. A feature that touches only your own data is low risk; the same functionality talking to an old accounting system is another matter entirely. The cost hides in the counterparty: undocumented APIs, slow approval cycles, fields that mean something different on each side. Ask the estimator to break integrations out as separate items, as this is where estimates break.
Non-functional requirements can easily double the number. An application support and maintenance services used by a handful of staff is a very different build from the same idea serving thousands of external customers. Audit and compliance requirements, availability guarantees, load handling, data retention rules and localisation all add measurable effort. State them early or expect the estimate to move later.
Who actually does the work matters a great deal. An hourly rate tells you very little on its own: an experienced engineer at a higher rate can be cheaper per delivered feature than two juniors who need heavy code review. Also ask what else appears on the invoice: coordination, QA, release engineering and analysis have to be done by someone, but these should be itemised.
The number in the proposal is not the total cost. Expect hosting, subscriptions and licences, monitoring difference between monolith and microservices a maintenance allowance annually. A common working assumption is that software development company in active use consumes a meaningful share of the initial investment annually in fixes, updates and small changes. Ignoring this has always been the most frequent planning error.