BROWSE DOCS
REFERENCE
DOCS / METHODOLOGY

Stage 3 — Build

The stage that runs hundreds of times. Every pull request is priced, compared against what is deployed, and checked against the rules in force for that product and environment. The verdict lands in the review, next to the change that caused it.

What runs on a pull request

Two commands, and they answer different questions. Keeping them separate keeps their failures legible — “we could not measure this” and “this costs too much” send you to different places.

COMMANDQUESTIONFAILS THE BUILD?
finowl breakdownWhat will this product cost per month, resource by resource?Only if it cannot produce a number — a missing bundle, an unresolved cluster reference, an unworded compute.
finowl guardDoes this change violate a rule that is in force here?Yes. Exit 1 on a blocking violation, 2 when a check could not run.

Both report to the platform under the product identity in finowl.yml, and they share one run identity — the CI pipeline id plus the commit SHA — so they merge into a single entry on the deployment timeline rather than appearing as two unrelated runs.

How the guard reaches a verdict

  1. Resolve the target. --targetis checked against the bundle's targets: block first, before the platform is called at all. Naming an environment that does not exist is answerable from the definition alone and should not cost a round trip to find out.
  2. Authenticate.The credential resolves once — in CI, from the pipeline's own OIDC identity.
  3. Fetch the rules.The platform merges account and organization policies, filters them to this environment, and fills a budget rule with this product's own budget. The CLI holds no policy file.
  4. Check the workload gate. Every compute the definition declares for this target must have a word in finowl.yml. Gaps are reported as one aggregated list — the complete to-do list, before any pricing call.
  5. Diff. databricks bundle plan produces the deployed and planned states. Both sides are priced with the same workload words, so the delta reflects the change and not a change of assumption.
  6. Evaluate. Cost thresholds against the diff; governance rules against the target-resolved bundle. Every rule produces a verdict with the resources that caused it.

Cost is evaluated at P90

The guard evaluates the P90 total rather than the midpoint. A gate that fires only when the expected case breaches the budget is a gate that lets through every change whose expected case is exactly at the limit — which is most of them, since teams size to their budget.

What Build deliberately does not check

  • Drift from the baseline estimate. Nothing fails a merge for costing more than the estimate said. The estimate is a projection made before the code existed; holding code to it would make the estimator a liability rather than a planning tool. The budget is what gets enforced.
  • Products with no budget. A budget rule finds no ceiling and drops out. The total is still reported and the run still recorded.
  • Rules in no policy. A rule that no policy carries never reaches the CLI. The rules page marks these Never runs.
  • Unchanged bundles. When the plan shows no cluster changes, the cost check reports no movement rather than re-litigating a total nobody touched.

Running it locally

Engineers can run every command on their machine before opening a pull request. The CLI detects that it is not in CI and files the run as a local preview: attributed to the developer's git identity, marked -dirty when the tree has uncommitted changes, and shown in a separate table.

# before you push, see what it will say
finowl breakdown --target dev
finowl guard --target dev

A local run never overwrites deployment costs and never feeds the dashboards. That separation is what makes local runs safe to encourage — the fastest way to stop engineers checking cost early is to make their experiments move the number the business reads.

The inner loop

When the guard blocks, there are three legitimate answers and the team picks one:

ANSWERWHAT IT MEANS
OptimizeSame outcome, cheaper shape. Smaller cluster, spot instances, a schedule that does not run hourly for a daily report.
DescopeLess outcome for the agreed money. The product owner decides what comes out.
Re-commitThe work genuinely costs more than was agreed. Go back to the sponsor, re-estimate, and commit a new figure with the reason.
NOTE
What the loop removes is the fourth answer — merge now, find out on the invoice. That one is not a decision, and it is the only one that reaches production without anybody choosing it.

Details of each command in the CLI reference, and of every rule type in Policies and rules.