AWS Cost Controls & Spending Limits
Last verified2026-06 — AWS billing features and their pricing change; verify current details in the Billing console before relying on exact numbers.
What is this?
A plain question with an annoying answer: "Can I tell AWS to stop charging me once I've spent $X?" No — AWS has no true hard spending cap. Unlike a prepaid phone that cuts off at zero, AWS keeps serving (and billing) past any limit you name. "Cost controls" is the set of tools you bolt on yourself to get close to a cap: tools that alert you, tools that automatically restrict new spend, and DIY automation that tears resources down. None of them is a switch AWS flips for you — you assemble the guardrail.
A "credit" (like the $180 free-tier promotional credit) is not a cap either: it offsets the bill, and once it's exhausted, real charges begin silently unless you've set up an alert.
Why it matters
Two reasons, one obvious and one that's the actual interview point.
a forgotten EKS control plane or a fat GPU instance quietly drains money. Everyone's first instinct ("set a hard limit") runs straight into the "there is no hard limit" wall, so knowing the real options matters.
a sudden cost spike is one of the loudest signals that your account is compromised. The single most common thing an attacker does with a leaked AWS key is spin up a fleet of expensive instances to mine cryptocurrency. The bill is often how the victim finds out. So cost controls are simultaneously a FinOps concern and a detection-and-containment control — and budget actions are a rare example of fully automated, account-level incident response.
Interviewers for cloud and incident-response roles ask this as "how would you limit blast radius / detect abuse in an AWS account?" — and "there's no hard cap, so here's what I'd actually do" is a strong answer.
How it works
Think of it as three layers, from "tells you" to "stops it" to "destroys it."
Layer 1 — AWS Budgets (alerting)
A budget is a monthly (or quarterly/annual) threshold on cost or usage. When actual or forecasted spend crosses a percentage of it, AWS emails you or publishes to an SNS topic (Simple Notification Service — AWS's pub/sub for notifications). It only notifies; it changes nothing.
- The first two budgets per account are free; beyond that there's a small per-budget daily charge.
- There's a managed "Zero spend budget" template that alerts the instant any charge appears — the right tripwire for a sandbox you expect to keep at $0.
- Cost Anomaly Detection is a sibling feature: a free, machine-learning monitor that learns your normal spend and flags unusual jumps (this is the one that catches a cryptomining spike without you having guessed the dollar amount in advance).
Layer 2 — Budget Actions (automatic enforcement)
This is the closest thing to a hard limit. A budget can carry an action that fires when a threshold is crossed. The action runs as a dedicated IAM role (the execution role) that AWS Budgets assumes. Three action types:
Spend crosses the action threshold (e.g. 100% of $25)
│
AWS Budgets evaluates (cost data lags several hours — NOT instant)
│
▼
Budget Action (approval_model = AUTOMATIC, or wait for manual approval)
├─ APPLY_IAM_POLICY → attach a Deny policy to a user / role / group
│ e.g. Deny ec2:RunInstances, eks:CreateCluster, rds:Create*
├─ APPLY_SCP → attach a Service Control Policy to an OU/account
│ (requires AWS Organizations; org-wide reach)
└─ STOP EC2 / RDS → stop instances matching a tag (kills running cost)The safe pattern: have the IAM-policy action deny only expensive create actions — never *, never anything in iam: or billing. That way the guardrail blocks new spend (you can't launch more instances) but you can still log in, delete the runaway resources to bring the bill down, and detach the policy when you're ready. A Deny * would lock you out of your own cleanup.
Two gotchas worth naming in an interview: the action is delayed (billing data isn't real-time, so enforcement lags hours behind the actual spend), and the SCP variant requires AWS Organizations — it doesn't exist for a lone standalone account, which only has the IAM-policy and stop-instance actions.
Layer 3 — DIY kill-switch (true teardown)
The only thing that behaves like a real "stop everything" is automation you build: a budget or CloudWatch billing alarm → SNS → Lambda function that terminates/deletes resources (terminate EC2, delete EKS clusters, etc.). It's the heaviest option and the only one that actually removes spend rather than freezing it. People build exactly this for throwaway sandbox accounts.
Preventing the spend in the first place (Service Control Policies)
Separate from budgets, SCPs (Service Control Policies) — guardrails attached to accounts/organizational units in AWS Organizations — cap what can ever be created, regardless of dollars:
(aws:RequestedRegion not in your allow-list) — attackers love spinning up in regions you never watch.
(ec2:InstanceType condition) — the most direct anti-cryptomining control.
you'll never use (SageMaker, Redshift, EMR).
SCPs are preventive (nothing expensive can launch) where budget actions are reactive (spend already started, now clamp down). Defense in depth uses both.
Security angle
The headline: leaked credentials + no hard cap = a five-figure cryptomining bill. This is the most common AWS abuse pattern, and it chains directly off the leaked-key story in the labs (see labs/ir-scenario and iam-deep-dive.md).
leaked AKIA key (committed to git / CI logs / stolen via SSRF→IMDS)
│
attacker: ec2 RunInstances × N (GPU / large types) across MANY regions
│
instances dial a mining pool; bill climbs thousands/day
│
DETECTION SIGNALS, in roughly the order they fire:
• Cost Anomaly Detection — spend jumps off the learned baseline
• GuardDuty — CryptoCurrency:EC2/BitcoinTool.B!DNS, UnauthorizedAccess:* findings
• CloudTrail — a burst of RunInstances from a new IP / new region / new principal
• Budget alert — you cross the threshold (often the slowest to notice)
│
CONTAINMENT:
• budget ACTION auto-denies ec2:RunInstances → no new instances
• disable/rotate the leaked key; quarantine the principal
• SCP (deny large types + unused regions) limits the blast radius pre-emptivelyOther security points an interviewer probes:
By default IAM users can't see the billing console; an account admin must activate IAM access to billing. The root user always controls billing, and an SCP can't fully restrict the management account's root — which is why root gets locked away with hardware MFA. (See iam-deep-dive.md.)
It's assumed by the budgets.amazonaws.com service; its trust policy should pin aws:SourceAccount to your account so another tenant can't trick the service into acting on your role. Scope its permissions to only attaching the one deny policy to the one target.
not just mining: a spike in NAT gateway / inter-region / internet egress charges can be the financial shadow of someone copying your S3 buckets out.
Interview Q&A
No — AWS has no true hard cap; it keeps serving and billing past any number. The closest you get is layering tools you assemble yourself: AWS Budgets for alerts, a budget action that auto-attaches a deny policy or stops tagged EC2/RDS when you cross a threshold, and for an actual teardown a Lambda kill-switch triggered off the budget. The catch is that budget actions lag several hours behind real spend because billing data isn't real-time, so they clamp the bleeding rather than prevent the first dollar.
Because a sudden cost spike is one of the loudest indicators of compromise — the most common thing an attacker does with a leaked AWS key is launch a fleet of GPU instances to mine cryptocurrency, and the bill is often how the victim notices. So budgets and Cost Anomaly Detection double as detection, and a budget action that denies ec2:RunInstances at a threshold is genuinely automated containment. Cost monitoring is a security control, not just a finance one.
Make the APPLY_IAM_POLICY action attach a policy that denies only expensive create actions — ec2:RunInstances, eks:CreateCluster, rds:Create* — never a blanket Deny * and nothing touching IAM or billing. That blocks new spend while you can still sign in, delete the runaway resources to bring the bill down, and detach the policy afterward. Pin the execution role's trust to budgets.amazonaws.com with an aws:SourceAccount condition so it can't be abused as a confused deputy.
Budget actions are reactive — spend has already crossed a dollar threshold and you clamp down — while SCPs are preventive, capping what can ever be created regardless of cost, like denying unused regions or large instance types. SCPs need AWS Organizations and don't exist for a standalone account; budget actions work in any account but only offer the IAM-policy and stop-instance types without an org. Defense in depth uses both: SCPs to stop the expensive thing launching, a budget action to catch whatever slips through.
I'd treat it as a likely credential compromise driving cryptomining. Check Cost Anomaly Detection and Cost Explorer to see which service and region spiked — almost always EC2 in regions you don't use — then pull the GuardDuty findings (CryptoCurrency and UnauthorizedAccess) and the CloudTrail RunInstances events to identify the principal and source IP. Contain by disabling the leaked access key, denying ec2:RunInstances (or stopping/terminating the instances), and then rotate credentials and add an SCP denying unused regions and large instance types so it can't recur.