Skip to content

Cost and budgets

cairn treats cost as something you decide on before the money is spent, and check afterwards. Three mechanisms work together: a pricing step you can gate on, a budget that flow legs reserve against, and cost thresholds that belong to the environment.

cairn does not guess a price for you. Pricing is a step in the pipeline, done by an operator that knows how:

OperatorPrices
cost/tokensmodel calls, from a token count and the model’s price; it refuses to price a model it does not know instead of reporting $0
compute/estimatea GPU run: hours, memory and dollars
compute/quotelive GPU offers, next to cairn’s own estimate

Because the price is an ordinary step output, a gate can read it.

The public serving/batch-inference pipeline prices the job, then lets a predicate decide whether it may start:

- id: estimate
task: cost/tokens
with:
model: $input.model
rows: $input.rows
prompt_tokens: $input.est_prompt_tokens
completion_tokens: $input.max_tokens
sample_prompt: $input.sample_prompt
- gate: cost
depends_on: [estimate]
predicate: steps.estimate.usd <= input.max_cost_usd

When the estimate is above max_cost_usd (5 dollars unless you pass another value), the gate blocks and the pipeline stops before the batch leg runs. The same rows input becomes the batch job’s hard row limit, so the job cannot process more than the gate priced. A last spend leg prices the tokens the job really used, so the record holds the measured cost, not the estimate.

A pipeline declares its budget in governance:

governance:
budget: {usd: 25}
series: batch-inference
approvers: platform
  • budget.usd is the pipeline’s spending cap. Every gate shows the person deciding how much the pipeline has spent so far against it.
  • series names a group of runs that share that cap. Before a flow leg starts its engine, it reserves the pipeline’s governance.estimated_usd against the series cap. The reservation is atomic (a lock per series on Postgres), so two legs cannot both take the last dollar.

When a reservation would go over the cap, the leg fails before it spends, with this message (values filled in):

series '<series>': this run's estimate $<estimate> would exceed the $<cap> cap
($<spent> spent, $<held> reserved by in-flight runs). Raise the budget or start a new series.

A finished leg settles its reservation. A failed or cancelled leg releases it. A retried attempt reserves again, because a retry is new spend.

The cost/gate operator turns a GPU estimate into a pass, warn or fail verdict. Its thresholds are set by the environment, not by the pipeline:

[profile.config."cost/gate".thresholds]
max_usd = 40
warn_usd = 25
require_fit = true
ThresholdDefaultMeaning
max_usd0 (no cap)an estimate above this fails
warn_usd0 (off)an estimate above this warns, without blocking
require_fittruea run that will not fit the GPU’s memory fails

These are governance settings: a pipeline or a run cannot loosen them. The shipped profiles leave them at their defaults, so set them in your deployment’s profile. The training/finetune pipeline is one that runs this gate before a GPU is provisioned.

Every run records its cost split into model calls, GPU and storage, plus a total. The pipeline page and Runs add them up per leg and per pipeline.