# Budgets and spending caps

> Put an enforced limit on what an org, a project or a labelled group of work can spend, and cap any single run.

Source: https://nodus-platform-site.pages.dev/docs/guides/billing/budgets/
Build revision: 211ad9f836655b1c3a2668c4693e442471f28614

Nodus enforces two kinds of spending limits. Both are checked before any paid work starts and again every few minutes while it runs, so a limit always stops spend instead of reporting it afterwards.

* A **Budget** limits what matching work across your org can spend in a month or in total.
* **`maxCostUSD`** caps one object: a Job, Pipeline, Sweep, TrainingJob, Sandbox, Workspace, Function, Agent or InferenceEndpoint. A cap on a Pipeline or Sweep is shared by every run it creates.

## Create a Budget

```yaml
apiVersion: nodus.dev/v1
kind: Budget
metadata:
  name: research-monthly
spec:
  limitUSD: "500.00"
  period: Monthly          # a UTC calendar month; Total counts from creation
  scope:
    project: research      # leave out for the whole org
    selector:
      matchLabels: {team: nlp}
  action: Block            # Notify only sends notices
  thresholds: [50, 80, 100]
  notify:
    emails: [research-leads@example.com]
```

Terminal window

```bash
nodus apply -f budget.yaml
nodus get budget research-monthly
```

`nodus get budget` shows what is spent, what is held for running work, what remains and the thresholds already notified this period. An org can have up to 50 Budgets.

## What a Budget covers

A Budget counts every hold and charge of work in its project whose labels matched the selector **when the work was created**. Changing a running Job’s labels does not move it out of a Budget. A Budget you create while work is already running starts covering that work within 5 minutes.

## What happens at the limit

With `action: Block`:

* New work in scope is refused with `402 BudgetExceeded`, naming the Budget, what is left and what the work needs:

  ```text
  budget "research-monthly" has $0.40 left of $500.00 this month; job "train-a" needs $3.20.
  fix: raise spec.limitUSD on budget/research-monthly, or wait until 2026-11-01
  ```

* Running work in scope stops gracefully, as described in [When money runs out](https://nodus-platform-site.pages.dev/docs/guides/billing/when-money-runs-out/), with `Funded=False` and reason `BudgetExceeded`.

* Raising `spec.limitUSD`, switching to `Notify`, deleting the Budget or the start of the next month resumes it.

With `action: Notify`, nothing is refused; you only get the notices.

## Notices

Each threshold is sent once per period as a `BudgetThreshold` Event, a `budget.threshold` webhook and an email to the billing email, org owners and admins, and the addresses in `spec.notify.emails`. Reaching a `Block` limit also sends `BudgetExceeded` (webhook `budget.exceeded`).

## Cap a single run

```yaml
kind: Job
spec:
  maxCostUSD: "25.00"
```

A Job never holds more than its cap. When its spend reaches the cap, it checkpoints and becomes `Suspended` with reason `MaxCostReached`; raising `maxCostUSD` resumes it from the checkpoint. You can raise a cap at any time, but not lower it.

A Pipeline, Sweep or TrainingJob shares its cap with the Jobs it creates. Each child must fit both its own cap and its parent’s remaining cap, along with every matching Budget. A dry-run reports an insufficient spending limit in `status.estimate.blockingReasons` without reserving funds.
