Skip to main content

How to Set Up Budgets and Anomaly Detection Before the Bill Surprises You

6 min read
Set up AWS spend alerts

We configure budgets and Cost Anomaly Detection with the right people on each notification.

Finding out about a spend problem from the invoice means finding out weeks late. AWS gives you two different mechanisms for catching it earlier, and they are not interchangeable. A budget fires when a number you chose is crossed, while Cost Anomaly Detection models what your spend normally looks like and tells you when the shape changes. This walks through setting up both from the CLI, the delay each one carries between the spend happening and the alert arriving, who should be on which notification, and the charges neither one will catch for you.

Finding out about a spend problem from the invoice means finding out weeks late. The thing that caused it, a forgotten test cluster, a log group with no retention, a NAT gateway suddenly carrying replication traffic, has been running the whole time. The point of alerting on spend is to shorten that gap from weeks to about a day, which is usually the difference between a conversation and an incident.

AWS gives you two mechanisms and they are not interchangeable. A budget is a threshold you set yourself, and it fires when the number crosses the line you drew. Cost Anomaly Detection has no line. It builds a model of what your spend normally looks like and tells you when the shape changes, which catches the thing you never thought to draw a line around.

What a budget actually watches

AWS Budgets tracks cost, usage, Reserved Instance utilization and coverage, and Savings Plans utilization and coverage. For each one you can be alerted on actual spend after it has accrued, or on forecasted spend before it accrues. The forecasted alert is the one worth having, because an actual alert at your limit tells you the money is already gone.

The timing is easy to get wrong. AWS Budgets information is updated up to three times a day, and updates typically occur 8 to 12 hours after the previous update. AWS also states plainly that there can be a delay between when you incur a charge and when you receive a notification, because there is a delay between when a resource is used and when that usage is billed. A budget is not a circuit breaker. Treat it as a signal that arrives within a day, not within a minute.

Create one on the account before you build anything clever. The budgets endpoint lives in us-east-1 regardless of where your workloads run.

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
read -r -p "Monthly cost limit to track against: " LIMIT
read -r -p "Alert email: " ALERT_EMAIL

cat > /tmp/budget.json <<JSON
{
  "BudgetName": "monthly-account-cost",
  "BudgetLimit": { "Amount": "$LIMIT", "Unit": "USD" },
  "TimeUnit": "MONTHLY",
  "BudgetType": "COST"
}
JSON

cat > /tmp/notifications.json <<JSON
[
  {
    "Notification": {
      "NotificationType": "FORECASTED",
      "ComparisonOperator": "GREATER_THAN",
      "Threshold": 100,
      "ThresholdType": "PERCENTAGE"
    },
    "Subscribers": [{ "SubscriptionType": "EMAIL", "Address": "$ALERT_EMAIL" }]
  },
  {
    "Notification": {
      "NotificationType": "ACTUAL",
      "ComparisonOperator": "GREATER_THAN",
      "Threshold": 80,
      "ThresholdType": "PERCENTAGE"
    },
    "Subscribers": [{ "SubscriptionType": "EMAIL", "Address": "$ALERT_EMAIL" }]
  }
]
JSON

aws budgets create-budget \
  --region us-east-1 \
  --account-id "$ACCOUNT_ID" \
  --budget file:///tmp/budget.json \
  --notifications-with-subscribers file:///tmp/notifications.json

A single notification takes one SNS topic and up to ten email addresses, and a budget takes up to five notifications. That is enough to send the forecast warning to the team that can act on it and the hard threshold to whoever owns the number.

The daily budget is the underrated one. A monthly budget on a growing account spends most of the month comfortably under its limit, so a runaway that starts on the fourth has three weeks to run before anything fires. Change TimeUnit to DAILY in the same JSON and you get a far shorter fuse for the same effort.

What anomaly detection catches that a budget cannot

Cost Anomaly Detection runs machine learning models over your net unblended cost. After billing data is processed it runs approximately three times a day, and because it uses data from Cost Explorer, which has a delay of up to 24 hours, it can take up to 24 hours to detect an anomaly after the usage occurs. A new monitor takes 24 hours before it begins detecting, and a newly used service needs 10 days of historical usage data before anomalies can be detected for it.

You choose what it watches. A monitor is either AWS managed, which tracks every value in a dimension automatically and picks up new values as they appear, or customer managed, which tracks up to ten values you select. The dimensions are AWS services, linked accounts, cost allocation tags and cost categories. Start with the services monitor, since it needs no decisions from you.

aws ce create-anomaly-monitor \
  --region us-east-1 \
  --anomaly-monitor '{
    "MonitorName": "all-services",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "SERVICE"
  }'

If you tag by team or by environment, a managed tag monitor is what turns an alert into an owner. Give it the tag key and it evaluates every value of that key independently.

aws ce create-anomaly-monitor \
  --region us-east-1 \
  --anomaly-monitor '{
    "MonitorName": "per-team",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "TAG",
    "MonitorSpecification": { "Tags": { "Key": "team" } }
  }'

Who should receive which alert

The subscription decides the audience, and the frequency you pick decides the channel. IMMEDIATE notifies as soon as an anomaly is detected and requires an SNS topic. DAILY and WEEKLY are email summaries, the daily one being the top ten alerts from the previous day sorted by cost impact, generated at 00:00 UTC.

Route the immediate ones through SNS into the channel where the engineers who own that workload already are. Send the weekly summary to whoever owns the number. Keep a monthly budget threshold out of the on-call pager, because nobody can usefully act on it at three in the morning and it teaches people to ignore the pager.

The threshold on a subscription is either the anomaly's total cost impact or its total impact percentage, written as a threshold expression. The percentage form is the one that survives growth, since a fixed figure that was meaningful last year quietly becomes noise as the account gets bigger.

aws ce create-anomaly-subscription \
  --region us-east-1 \
  --anomaly-subscription '{
    "SubscriptionName": "engineering-immediate",
    "Frequency": "IMMEDIATE",
    "MonitorArnList": ["MONITOR_ARN"],
    "Subscribers": [{ "Type": "SNS", "Address": "SNS_TOPIC_ARN" }],
    "ThresholdExpression": {
      "Dimensions": {
        "Key": "ANOMALY_TOTAL_IMPACT_PERCENTAGE",
        "MatchOptions": ["GREATER_THAN_OR_EQUAL"],
        "Values": ["50"]
      }
    }
  }'

Anomalies below your threshold are still detected and still recorded. They simply do not notify anyone, and you can review them on the Detected anomalies tab when you have time.

The gaps to know about

Cost Anomaly Detection does not monitor third-party products and services bought through AWS Marketplace, with the exception of third-party foundation models on Amazon Bedrock. If Marketplace is a real line on your bill, a cost budget with the billing entity filter is what covers it.

A budget can also act rather than only alert. Budget actions can apply an IAM policy or a service control policy, or target specific EC2 or RDS instances, running either automatically or after your manual approval. Manual approval first is the sane default. An automatic deny policy that fires on a forecast can stop a deploy at the worst possible moment.

Neither mechanism replaces knowing what your resources are. They tell you something changed. Working out what changed still comes from consistent tagging and from Cost Explorer, which is where a cloud cost optimization engagement usually starts, and the alerting itself is a small part of ongoing AWS cloud management.

Frequently asked questions

What is the difference between AWS Budgets and Cost Anomaly Detection?

An AWS budget is a threshold set by hand, and it fires when spend crosses the line that was drawn. Cost Anomaly Detection has no line and instead models what spend normally looks like, alerting when the shape changes, which catches costs nobody thought to draw a line around. Budgets track cost, usage, and Reserved Instance and Savings Plans utilization and coverage, with alerts on actual or forecasted spend. The two mechanisms are not interchangeable.

How quickly do AWS Budgets alerts arrive after a charge?

Expect a signal within about a day. AWS Budgets information is updated up to three times a day, typically 8 to 12 hours after the previous update, and AWS states there can be a delay between incurring a charge and receiving a notification because usage is billed after the resource is used. A budget is not a circuit breaker, which is why the forecasted alert matters more than an actual alert at the limit, when the money is already gone.

How do I create an AWS budget alert from the CLI?

Call aws budgets create-budget with --region us-east-1, since the budgets endpoint lives there wherever workloads run, passing the account ID, a budget JSON with BudgetType COST and TimeUnit MONTHLY, and a notifications file. A useful pair is a FORECASTED notification at 100 percent and an ACTUAL notification at 80 percent of the limit. Setting TimeUnit to DAILY gives a far shorter fuse, because a runaway that starts on the fourth otherwise has three weeks before a monthly budget fires.

How long does AWS Cost Anomaly Detection take to detect a spike?

Detection can take up to 24 hours after the usage occurs. Cost Anomaly Detection runs approximately three times a day after billing data is processed, and it relies on Cost Explorer data, which has a delay of up to 24 hours. A new monitor also takes 24 hours before it begins detecting, and a newly used service needs 10 days of historical usage data before anomalies can be detected for it.

Which AWS Cost Anomaly Detection monitor should I create first?

Start with the AWS managed services monitor, created with aws ce create-anomaly-monitor in us-east-1 using MonitorType DIMENSIONAL and MonitorDimension SERVICE, since it needs no decisions. AWS managed monitors track every value in a dimension and pick up new values automatically, while customer managed monitors track up to ten selected values. Accounts tagged by team or environment should add a managed tag monitor on that key, which evaluates every value independently and turns an alert into an owner.

How should AWS Cost Anomaly Detection alerts be routed?

Send IMMEDIATE subscriptions, which require an SNS topic, into the channel where the engineers who own the workload already are, and send the WEEKLY email summary to whoever owns the number. The DAILY summary lists the previous day's top ten alerts by cost impact, generated at 00:00 UTC. A threshold on ANOMALY_TOTAL_IMPACT_PERCENTAGE survives account growth better than a fixed figure, and anomalies below the threshold are still recorded on the Detected anomalies tab.

Does AWS Cost Anomaly Detection monitor AWS Marketplace charges?

No. Cost Anomaly Detection does not monitor third-party products and services bought through AWS Marketplace, with the exception of third-party foundation models on Amazon Bedrock. Where Marketplace is a real line on the bill, a cost budget with the billing entity filter is what covers those charges.

Can an AWS budget stop resources automatically when spend runs over?

Budget actions can apply an IAM policy or a service control policy, or target specific EC2 or RDS instances, and they run either automatically or after manual approval. Manual approval is the sane default. An automatic deny policy that fires on a forecast can stop a deploy at the worst possible moment.

Read how we handle it in Cloud Cost Optimization.