Skip to content

Budgets & alerts

A budget is a spend cap that gets checked once a day and notifies an alert channel when it’s crossed. It’s separate from anomaly detection, which flags unusual day-to-day spikes — a budget tracks a running total against a fixed limit for one calendar period.

A budget watches one of four things:

  • Account — total spend across every enabled cost source.
  • Cost source — spend from one connected provider only (AWS, Datadog, and so on).
  • Team — one team’s tagged spend.
  • Tag value — spend matching one value of any tag you’ve defined (see Virtual tagging & cost allocation).

A team-scoped budget is a special case of a tag-scoped budget. Every team reserves a value under a built-in team tag, so “this team’s spend” is the same computation as any other tag-scoped budget with the tag key fixed to team. Teams stay a separate option in the budget form because a team is a named group of people with members, not just a label — and a team-scoped budget keeps working if you rename the team, since it points at the team’s ID rather than its display name.

Because tag-scoped budgets (including team budgets) depend on a tagging rule existing, a budget can be created before the rule that feeds it. Until a rule assigns that tag value, the budget reads as $0 spent — Plutus warns about this on the budget itself rather than blocking creation, so you can set the budget up first and back-fill the tagging rule after.

If the tag key the budget watches uses shared-cost splitting or redistribution, the budget’s spend figure reflects the split weights and any redistributed share, the same way the tag’s chart does — see Virtual tagging & cost allocation for how that changes what a tag value’s total means.

Editing a tag rule changes what a tag-scoped budget counts, but a budget’s figure is a stored rollup rather than a live query, so it lags the charts briefly and never revises a period that has already closed. That asymmetry is the one exception to retroactive tagging and is described in full under Rule changes apply retroactively.

Each budget has its own period: weekly, monthly, quarterly, or annual. Periods follow the UTC calendar (a monthly budget covers the calendar month, and a weekly one runs Monday to Sunday), not the date your Plutus plan renews. Each budget has a state, recomputed once a day for its current period:

  • ok — spend is below the warning threshold.
  • warning — spend has crossed the warning threshold (80% of the budget amount, by default — configurable per budget).
  • exceeded — spend has reached or passed the budget amount.

Example: an account sets a $10,000 monthly account-wide budget with the default 80% warning threshold. Spend crosses $8,000 partway through the month — the budget flips to warning and notifies its subscribed channels. It stays in warning (no repeat notification) until spend reaches $10,000, at which point it flips to exceeded and notifies again. If spend later drops back under $8,000 — a credit, a corrected sync — the state also drops back, but only upward transitions send a new notification.

That’s the general rule: a notification fires only the first time a budget crosses into a worse state, not on every check after. An account that’s already over budget doesn’t get paged again every day it stays over.

Jira and PagerDuty channels are the one exception: since those open a ticket or incident rather than post a message, a downward move closes what the upward move opened instead of staying silent. See Recovery: closed automatically when the condition clears.

A team-scoped budget works the same way against its own tagged total. If the platform team has a $5,000 monthly budget and their tagged spend hits $4,000, the budget goes to warning and whichever channel is subscribed to it gets notified — independent of the account-wide budget’s own state.

A budget can also send a “projected to exceed” alert before it reaches the limit. Forecast alerts are on by default for new budgets. When they’re on, the alert fires when the current run rate projects spend over the budget amount by the end of the period, and the budget hasn’t already been exceeded. It fires when the projection moves from on track to over budget, not on every daily check while it stays over. It goes to the same subscribed channels as the warning and exceeded alerts.

A budget’s spend figure is always billed cost — what the provider actually charged — never amortized cost, regardless of which one the chart next to the budget happens to be displaying. See Billed vs. amortized cost for the full distinction. This means a budget can read differently from a chart set to show amortized figures for the same period — that’s expected, not a bug, and it’s the same reason the account-wide spend limit on your plan is evaluated on billed cost too.

A channel is one delivery destination. Six types:

  • Slack — either a manually pasted incoming-webhook URL, or a connected Slack workspace (OAuth), which lets you pick any channel in that workspace without creating a new webhook per channel.
  • Teams — an incoming webhook URL.
  • Webhook — any URL you control. Plutus POSTs a JSON payload; if the channel has a secret configured, the request is signed so you can verify it came from Plutus.
  • Email — one or more recipient addresses.
  • Jira — creates a real issue in one project, using a write-scoped Jira credential of its own.
  • PagerDuty — creates a real incident through the Events API v2, using a service-scoped routing key.

The last two open something a person has to close, so they behave a little differently from the message-posting channels — separate credentials from the read-only Jira/PagerDuty event sources, a per-channel hourly send cap, and no digest delivery. They have their own setup forms under Alerts. The quick-create dialog doesn’t offer them. See Alert channels.

Create one channel per destination. To route different things to different places — AWS alerts to #devops, budget alerts to #finance — create a channel for each destination and subscribe it to what you want, rather than trying to configure routing on a single channel.

A channel doesn’t receive anything until it’s subscribed to a trigger. There are two kinds of subscription:

  • A specific budget — the channel is notified when that budget crosses into warning or exceeded.
  • An account-wide trigger — not tied to any one budget. Three of these exist: cost anomalies (see Anomaly detection), event-ingestion limit overage, and commitment expiration (an under-utilized AWS Reserved Instance or Savings Plan, or Azure Reservation, nearing its end date — see Savings & optimization). Each is its own checkbox on the channel, so subscribing to one doesn’t subscribe to the others.

The same channel can be subscribed to several budgets, and the same budget can notify several channels — a warning transition on the platform team’s budget might go to both #platform and a shared #finance-alerts channel.

All four trigger kinds use the same delivery path and the same delivery log — they’re different triggers, not different pipes.

A digest is a different thing from a budget alert: it’s a recurring summary sent on a schedule (weekly or monthly), not a notification triggered by crossing a threshold. Where a budget alert tells you “spend just crossed $8,000,” a digest tells you “here’s what happened this week” — total spend, the period-over-period change, the biggest movers, any budgets that need attention, and open savings recommendations — whether or not anything crossed a threshold.

A few things distinguish digests from the threshold-based alerts above:

  • A digest targets one channel directly, chosen when you create it, rather than going through the subscription model. This is deliberate: you might want a weekly AWS-only summary in #devops and a separate monthly whole-account summary in #finance — different cadence, different scope, different destination, which doesn’t fit “which channels are subscribed to this account.”
  • A digest can be scoped to the whole account, one cost source, or one tag value (team digests are a tag-scoped digest under the team tag, the same relationship budgets have to tags). A tag-scoped digest’s biggest movers are the things feeding that tag value, not other tag values — so a team’s digest never publishes another team’s numbers.
  • A digest always reports on a completed period, never the one still in progress. A weekly digest sent Monday morning covers the previous Monday through Sunday, not the week that just started.
  • If there’s no cost data for the period, nothing is sent — a digest that fires on an empty or not-yet-arrived period would report a false zero.

Digest delivery goes through the same channels, the same delivery log, and the same currency handling as budget alerts — it’s a different trigger, not a different pipe.