Every quarter the finance team asks me the same question: "What's the AWS bill going to be next month?" For a long time my answer was a shrug and a number I'd half-eyeballed from last month's invoice. That stopped being acceptable once our spend crossed six figures and a single misconfigured pipeline could swing the bill by 20% in a weekend.

This is how I now produce a defensible forecast and, more importantly, how I get paged before reality blows past it. The two tools that do the work are Cost Explorer and AWS Budgets, and the trick is using them together rather than treating either as the whole answer.

Cost Explorer forecasts, and their limits

Cost Explorer has a built-in forecast that uses an ML model on your historical usage to project spend forward, complete with an 80% prediction interval. You can pull it programmatically rather than clicking through the console:

aws ce get-cost-forecast \
  --time-period Start=2026-07-01,End=2026-08-01 \
  --metric UNBLENDED_COST \
  --granularity MONTHLY \
  --prediction-interval-level 80

This is genuinely useful, but understand what it is: a time-series projection of your recent usage. It assumes tomorrow looks like the trailing weeks. It does not know you are launching a new service next Tuesday, nor that a Reserved Instance term expires mid-month. The forecast quality also degrades badly if you have fewer than a couple of months of stable history. Treat it as a baseline you adjust, not gospel.

Separating run-rate from one-offs

The single most important step in forecasting is splitting your bill into a stable run-rate and known deltas. I group cost by service and usage type and look at the trailing 30 days:

aws ce get-cost-and-usage \
  --time-period Start=2026-05-25,End=2026-06-24 \
  --granularity DAILY \
  --metrics "UnblendedCost" \
  --group-by Type=DIMENSION,Key=SERVICE \
  --filter '{"Not":{"Dimensions":{"Key":"RECORD_TYPE","Values":["Credit","Refund"]}}}'

The RECORD_TYPE filter matters: leaving credits and refunds in the data inflates or deflates your run-rate in ways that won't repeat. Once I have a clean daily run-rate, the forecast is just: (daily run-rate × days in month) + known deltas − expiring commitments. The known deltas are the part a model can never give you; they live in your team's roadmap.

Budgets as guardrails, not just reports

A forecast is worthless if nobody notices when it's wrong. AWS Budgets supports two alert types that I use differently: ACTUAL alerts fire when spend has already crossed a threshold (too late to prevent, good for accountability), and FORECASTED alerts fire when Budgets predicts you will exceed the threshold by month-end (early warning). I always set both.

{
  "BudgetName": "monthly-prod-spend",
  "BudgetLimit": { "Amount": "42000", "Unit": "USD" },
  "TimeUnit": "MONTHLY",
  "BudgetType": "COST",
  "CostFilters": { "TagKeyValue": ["user:env$prod"] }
}

Notifications at 80% actual, 100% actual, and 90% forecasted cover most cases. Wire the SNS topic to a Slack webhook via a small Lambda so the alert lands where people actually look, not in an inbox nobody checks.

A workflow that holds up

StepToolOutput
Pull clean run-rateCost Explorer APIDaily $ minus credits/refunds
Get ML baselineget-cost-forecastProjection + 80% interval
Add roadmap deltasSpreadsheet / your headAdjusted forecast
Set guardrailsAWS BudgetsForecasted + actual alerts
A forecast you don't compare against actuals is a guess with extra steps. The value is in the variance review, not the number you ship to finance.

At month-end I diff the forecast against actual spend per service and ask why the biggest misses happened. Nine times out of ten it's an untagged new workload or an autoscaling group that ran hot. That feedback loop tightens the next forecast far more than any model tuning.

Takeaways

  • Cost Explorer's forecast is a trailing-usage baseline; it can't know your roadmap, so always adjust it with known deltas and expiring commitments.
  • Filter out credits and refunds before computing run-rate or your numbers will lie to you.
  • Use both FORECASTED and ACTUAL Budget alerts, and route them to Slack so they're actually seen.
  • Run a monthly forecast-vs-actual variance review; that loop improves accuracy more than anything else.