Everything so far measures cost after it has been incurred. This chapter is about the one place a cost decision can still be cheap to reverse: before the change is merged.
The argument for doing it there is not aesthetic. It is that the billing-side alerting most teams rely on is, by the vendors' own documentation, far too slow to function as a control.
What the alerting layer actually promises
AWS Budgets information "is updated up to three times a day", and "updates typically occur 8–12 hours after the previous update."
Google Cloud is blunter about the limitation. Its budget documentation carries a caution that for alerts-only budgets, "the budget doesn't automatically set a hard cap on spending", recommends setting the budget amount below available funds to account for reporting delay, and notes that after creating a budget "it may take several hours before receiving the first email or Pub/Sub notification" — on top of the separate delay between using a resource and that usage reaching Cloud Billing.
Azure notes that a newly created subscription may take up to 48 hours before all Cost Management features are usable, though a budget can be configured at creation time.
Put the AWS figure in operational terms, because it is the most precise of the three. If updates arrive up to three times a day and consecutive updates are typically 8–12 hours apart, then a spend change that begins immediately after an update may be invisible for up to roughly 12 hours, and the alert that follows describes money already spent. On a runaway agent loop or an accidental expensive-tier deployment, twelve hours is not a warning. It is a post-mortem.
None of this is a vendor failing. Billing pipelines aggregate across regions and services and cannot be real-time at that scale. It is a design constraint, and the correct response to a design constraint is to put the control somewhere else.
The three gates, cheapest first
1. The pull request. Static checks against the diff, before anything runs. These catch the largest class of avoidable cost because they catch it before it exists:
- an accelerator instance type appearing in infrastructure code that is not on the approved list
- a model identifier changing to a more expensive tier
- a removed or weakened
max_tokens, step limit, or loop bound - a new always-on resource with no autoscaling or schedule attached
- a storage class or retention change that quietly makes data permanent
These are grep-and-policy checks, not forecasts. They are unglamorous and they are the highest-yield thing in this chapter, because the cost of failing them is a code-review comment.
2. The plan step. Where infrastructure-as-code produces a diff before applying, that diff is a cost artifact. A resource count and instance family are enough to reject a change without predicting a dollar figure — and rejecting on "this adds four always-on GPU instances" is more defensible than rejecting on an estimate anyone can argue with.
3. Runtime ceilings. Hard caps that fail closed: request budgets, per-job token limits, step counts, timeouts. These are the only layer that acts inside the twelve-hour window above, which is precisely why they cannot be optional.
Billing alerts sit below all three. They remain worth having — as detection of the thing every gate missed, not as the gate.
Make it a comment, not a wall
The rule that decides whether cost-in-CI survives contact with a team: fail the build only on the checks that are objective.
An instance type not on the approved list is objective. A missing token cap is objective. "This change looks expensive" is a forecast, and forecasts that block merges get disabled within two sprints — usually during an incident, permanently.
So: hard-fail the deterministic policy checks, and post everything else as a comment on the pull request. A comment that says "this adds two p5 instances; current approved list is g6 and below" changes the design conversation without ever becoming the thing standing between a team and a deploy.
What to do with the vendor alerts you keep
Because they are lagging by design, the useful configuration is different from the intuitive one.
- Alert on forecast as well as actual. AWS Budgets supports alerting on both accrued and forecasted spend; forecast alerts are the only ones with any chance of arriving before the money is gone.
- Set the threshold below the number that matters, exactly as Google's documentation recommends, because the reporting delay means the real figure is always ahead of the reported one.
- Wire the notification to a channel with an owner, not to an inbox. An alert with a twelve-hour head start still needs someone to read it.
- Where a hard stop is genuinely required, use an action, not an alert. AWS Budgets can run a budget action when a threshold is crossed — applying an IAM policy or a service control policy, or targeting specific EC2 or RDS instances, either automatically or after manual approval. That is a control. Note the documented boundary: from a management account you can apply an SCP to another account, but you cannot target that account's EC2 or RDS instances.
The honest limit of this chapter
The latency figures above are quoted from vendor documentation and are checkable. The gate design is not measured — no vendor publishes data on how much spend pull-request checks prevent, and this book will not invent a percentage for it.
What the sources do establish is the load-bearing claim, and it is enough to act on: the billing-side alert cannot be your control, because all three providers document a delay between spend and signal, and one of them states outright that an alerts-only budget is not a cap. Everything else in this chapter follows from taking that sentence seriously rather than assuming the dashboard is watching.