The biggest cost driver is never technology — it is almost always unclear scope. Every open question in the requirements is converted into a contingency in the estimate. A supplier that has no visibility into the exceptions and edge cases will assume the worst. Investing a few days in a discovery phase can cut the final cost by far more than any rate negotiation.
Connections to other systems are another reliable source of cost. A form that saves data is low risk; the same functionality wired into an old accounting system is another matter entirely. The unknown sits in the other system: rate limits and sandbox access, waiting ruby on rails vs laravel someone else's team, inconsistent data. Ask each bidder to list every external system, since this is where estimates break.
Non-functional requirements can easily double the budget. An application used by a small internal team is a very different build from the same functionality serving a hundred thousand users. Security reviews, uptime targets, scalability, data retention rules and accessibility add weeks of work. State them early or it outsourcing services else expect them to arrive later as change requests.
The team you are quoted matters a great deal. An hourly rate says little on its own: a senior engineer at twice the price can be less expensive in the end than two juniors who need heavy code review. Check too who else is billed: coordination, QA, infrastructure work and design are real work, but they must be named rather than hidden inside a blended rate.
The quoted figure is never the full cost of ownership. Plan for hosting, paid APIs, monitoring and a change budget for every year the software development for regulated industries runs. A reasonable rule of thumb is that a live system requires a meaningful share of the initial investment annually for updates, security patches and small improvements. Leaving it out of the budget is the classic mistake.