organization_budget — version 2.0

Source: presets/organization-budget.satz

Purpose

Budgets on the infrastructure billing account with alert thresholds: one for the whole account, and one per entry of budgets for a set of projects or folders.

WHAT AN ENTRY IS. { name amount }, and optionally projects, folders, email and import_id. The first entry of budgets is the organisation's budget, global-budget, built from budget_amount and budget_notification_email. Binding budgets in the estate replaces the whole list, so an estate that adds budgets writes that entry too; a project asks for its own with contributes_budgets, checked by satz check-request.

WHAT A BUDGET COUNTS. An entry with neither projects nor folders counts the whole billing account. projects lists projects/<number> — the project NUMBER: "projects/${{google_project.<label>.number}}" for a project the estate declares. folders lists folders/<id> or organizations/<id>; google_folder.<label>.name already has that form. A budget lives on the billing account whatever it counts, so a project billed to another account is not counted here.

WHO IS TOLD. The billing account's administrators and users get every alert by e-mail from Google, with no resource — the group presets/billing-account-permissions.satz grants roles/billing.admin. An entry with an email also gets an e-mail notification channel in budget_channel_project (the infrastructure project), named in its budget; no Pub/Sub is involved. budget_default_recipients_off stops the mails to the billing account's administrators and users for the budgets that have a channel; a budget without one keeps them, so no budget alerts nobody.

ADOPTING AN EXISTING BUDGET. Give its entry import_id = "billingAccounts/<account>/ budgets/<id>" (gcloud billing budgets list --billing-account=<account>); satz adopt does not resolve budgets. An empty import_id creates the budget.

Use it

params {
  // the pack's own defaults — copy only the lines you change
  budget_amount = "1000"
  budget_currency = "EUR"
  budget_threshold_rules = [
    { threshold_percent = 0.5 spend_basis = "CURRENT_SPEND" },
    { threshold_percent = 0.8 spend_basis = "CURRENT_SPEND" },
    { threshold_percent = 1.0 spend_basis = "CURRENT_SPEND" },
  ]
  budget_notification_email = ""
  budget_default_recipients_off = false
  budget_channel_project = infra_project_name
  budgets = [ { name = "global-budget" amount = budget_amount } ]
}

use "presets/organization-budget.satz"

Needs from outside the pack:

Params

param default
budget_amount "1000"
budget_currency "EUR"
budget_threshold_rules [ { threshold_percent = 0.5 spend_basis = "CURRENT_SPEND" }, { threshold_percent = 0.8 spend_basis = "CURRENT_SPEND" }, { threshold_percent = 1.0 spend_basis = "CURRENT_SPEND" } ]
budget_notification_email ""
budget_default_recipients_off false
budget_channel_project infra_project_name
budgets [ { name = "global-budget" amount = budget_amount } ]

Questions

What to ask before this pack is configured, and what changing the answer costs.

asks about prompt reversal blast recommends
budget_amount The organisation budget's amount per calendar month, in whole units of the billing account's currency edit none —
budget_currency The billing account's currency (ISO 4217, for example EUR or USD) edit none —
budget_notification_email An address that gets the budget alerts beside the billing account's administrators — a group's address, never a person's edit none —
budget_default_recipients_off Stop mailing the billing account's administrators and users for the budgets that have an address of their own? edit none —

budget_amount — Alerts go out at 50, 80 and 100 % of it. Too high and the alarm comes after the money is gone; too low and the alerts are noise nobody reads.

budget_currency — A budget is stated in the billing account's own currency; any other is refused when the budget is created.

budget_notification_email — Google mails the billing account's administrators and users on its own. An address here adds an e-mail notification channel, for a team that holds no billing role.

An empty answer, "", is an answer: the billing account's administrators and users alone.

budget_default_recipients_off — A project's budget then reaches the project's team alone. A budget without an address keeps mailing the administrators, so no budget alerts nobody.

Contributes

resource type labels
google_billing_budget one per entry of budgets, by name, one per entry of budgets, by name
google_monitoring_notification_channel one per entry of budgets, by name

Requests

What a project may add to this pack's lists, through contributes_<param> in a file the estate uses after a reviewed pull request; satz check-request checks such a file.

list key fields description
budgets name name matching [a-z][a-z0-9-]*, amount matching [0-9]+, projects, folders, email matching ([^@: ]+@[^@: ]+)?, import_id A budget: its name, its monthly amount, the projects (projects/<number>) or folders (folders/<id>) it counts, and the address its alerts go to

Claims

None — this pack proves no control by itself.

History

version date change
2.0 2026-10-02 amount, currency, thresholds and recipients are params, budget_amount and the recipients asked; budgets adds budgets for projects or folders, each with an optional e-mail channel, as a request point; an existing budget is adopted through an entry's import_id, the placeholder id is gone
1.0 2026-08-20 organization budget with threshold alerts ("import-id" example)

The whole library's history: the changelog in presets/CHANGELOG.md.

Notes

The "import-id" in the pack is a placeholder for adopting a budget that already exists — satz adopt does not resolve budgets, so the id is filled by hand. Delete the line for a fresh budget, or the apply tries to import something that is not there.

The thresholds alert; they do not cap spend.