CPU ≥ 5%: the auto-scaling threshold that inflated the EC2 bill 14×
Published on June 26, 2026

The symptom: cost spikes with no usage spike
The cost report for a transactional app on AWS showed EC2 swinging absurdly: US$11/day interleaved with US$160+/day, with zero correlation to real traffic. 99% of EC2 cost came from a single Auto Scaling Group of c6g.2xlarge instances.
The starkest case: Feb 1–2 cost US$271.56 vs ~US$22.92 expected — US$248.64 extra in two days. Daily peak US$162.34 against a US$11.46 baseline: 14× the normal bill.
Root cause: a ridiculous scale-up threshold
The ASG scale-out alarm was set to CPU ≥ 5% over 3 datapoints of 60s. Five percent. Any micro-variation in load — and especially every deploy, which momentarily bumps CPU — crossed the trigger and the ASG launched new instances. Since scale-down was conservative, the inflated fleet lingered, and each extra c6g.2xlarge bills by the hour.
Auto scaling isn't "more elastic is better". An over-sensitive trigger turns noise into a bill — and deploys into cost incidents.
How to measure: Cost Explorer by USAGE_TYPE
Before touching anything, prove where the cost comes from. Cost Explorer via CLI, grouped by usage type, isolates the ASG's BoxUsage:
aws ce get-cost-and-usage \
--time-period Start=2026-02-01,End=2026-03-01 \
--granularity DAILY \
--metrics UnblendedCost \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Elastic Compute Cloud - Compute"]}}' \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--query 'ResultsByTime[].Groups[?contains(Keys[0], `BoxUsage`)]' --output tableThat's what revealed the daily spikes concentrated on deploy days — not on high-traffic days.
The fix: raise the threshold and separate deploy from scaling
The main fix was raising the scale-up trigger from 5% to a realistic band (40–50%), with a longer evaluation period, so only sustained load — not noise or a deploy — drives scaling. Estimated savings: ~US$150/month on that ASG alone, by killing the phantom fleet.
# before (ridiculous trigger)
ScaleUpThreshold: 5 # CPU% over 3x60s → any deploy scales
# after (real sustained load)
ScaleUpThreshold: 45 # CPU% over 5x60s
ScaleDownThreshold: 25 # healthy deadband between up and downA complementary caution: the deadband between scale-up and scale-down must be wide enough to avoid flapping, but not so wide the fleet gets stuck (a topic for another post).
Lessons
1. A low scale-up threshold is cost, not resilience. 5% CPU is noise. Start at 40–50% sustained load and tune with data.
2. Deploys scale the fleet if the trigger is sensitive. Cost spikes concentrated on deploy days are the signature of the problem.
3. Measure by USAGE_TYPE before acting. Cost Explorer grouped by BoxUsage proves which ASG/instance drives cost, instead of guessing.
Conclusion
Elasticity is great when it responds to real demand. A 5% trigger responds to ghosts: metric noise and the deploy pipeline itself. The fleet inflated, nobody watched the alarm, and the bill grew 14× silently. One config line — the right threshold — brought cost back to the size of usage.