How clients should budget a software project

Build a software budget from delivery assumptions, named risks, operating costs, and explicit decisions about what happens when scope changes.
Budget a release boundary
An estimate becomes useful when everyone agrees what it buys. For an example appointment portal, “booking” might mean displaying available slots, reserving one, sending confirmation, and letting staff correct mistakes. It might also imply payments, recurring appointments, and importing historical records. Those are different commitments.
Ask for a release boundary expressed as observable behavior, plus exclusions. Separate the delivery forecast from the spending limit. The forecast describes the likely cost under stated assumptions; the limit defines when a sponsor must decide to reduce scope, spend more, or stop. Treating those as the same number hides the decision until too late.
Make assumptions visible in the estimate
A range is only useful if its endpoints have explanations. In this illustrative budget record, uncertainty sits in the calendar integration rather than being spread as an unexplained allowance across every task. The YAML is a planning document for review, not a procurement standard or a billing configuration.
release: staff-assisted-booking
currency: EUR
cost_basis: excluding_tax
scope:
included: [availability, reservation, confirmation, staff_cancellation]
excluded: [payments, recurring_bookings, historical_import]
assumptions:
- Calendar sandbox is available before integration work starts
- One office and one appointment type are in the first release
risk:
name: calendar_conflict_handling
next_step: reproduce competing reservations in the sandbox
owner: technical_lead
spending_control:
limit: to_be_agreed
review_trigger: forecast_exceeds_approved_limit
decision_owner: client_sponsor
operating_costs:
- hosting_and_monitoring
- message_delivery
- support_and_dependency_maintenance
Price learning as a bounded piece of work
An integration spike should have a question, a time limit, and an output. For the calendar example, the question is whether simultaneous reservations can be rejected reliably. The output is a small test against a vendor sandbox, a description of observed errors, and a revised implementation estimate. It is not an indefinite discovery phase.
If the experiment fails, make the alternative explicit: staff confirmation before accepting the appointment, a different integration, or removing live booking from the release. The budget can then compare concrete alternatives. Do not imply that discovery guarantees certainty; it can reveal a dependency that remains outside either team’s control.
Include work around the feature
Request separate visibility for data cleanup, test environments, accessibility checks, migration rehearsal, release preparation, and support handover. These tasks may not add screens, but someone must do them. Ask who supplies content, approves copy, and resolves conflicting records, because a supplier estimate may assume client effort.
Recurring costs need an owner and a forecast period. A message-based service may have usage charges as well as engineering costs. State the assumed usage and what happens if it grows. Avoid a universal contingency percentage: a known but unmeasured import is a different risk from ordinary implementation variation.
Review remaining work, not only money spent
At each agreed checkpoint, compare accepted scope, actual spend, outstanding decisions, and the forecast to finish. A project can spend exactly to plan while delivering less usable functionality than expected. A demonstration should therefore use the same acceptance cases that defined the budget.
For a new request, show the effect on the remaining release: substitute it for another item, move the deadline with an approved cost change, or queue it for later. Record the sponsor’s decision. That gives both sides a working change process instead of relying on an argument about whether a vague original phrase included the request.

