TL;DR: Fargate charges for provisioned CPU and memory, not used — so the "2 vCPU / 4 GB just to be safe" you picked at launch and never revisited is a silent leak, usually larger than teams expect. An API task provisioned at 2 vCPU / 4 GB whose p95 is 0.5 vCPU / 1.5 GB is paying ~4× the CPU it needs, every hour, forever. Measure actual usage in Container Insights, size to p95 + ~25% headroom, and cut 30–60%. It's a 20-minute, high-confidence win — and a quarterly habit, not a one-time project.
The numbers
- Bill = provisioned, not used — idle at 5% still pays full rate; CPU/memory come in fixed combos, so plan both axes together.
- Size to p95, not average or max: average undersells a bursty task (15% avg with 80% peaks), max oversells (a once-a-month spike shouldn't drive everyday cost); p95 + 20–30% headroom is "normal busy load with margin."
- Field examples: a fintech's 50 tasks at 1 vCPU / 2 GB with p95 at 0.25/1 moved to 0.5 vCPU / 1 GB — $430/mo saved, zero perf change; an image-worker farm cut to 0.5 vCPU / 1 GB for $620/mo (plus $1,000+/mo once they added autoscaling); an enterprise's "always provision 2×" policy cut 4/8 → 2/4 for ~$2,100/mo and was still only 40% utilized.
Do this
- Enable CloudWatch Container Insights at the cluster level and pull p95 CPU and memory over 2 weeks for your top task definitions by hourly cost.
- Right-size to (p95 × 1.25) rounded up to the next valid Fargate combo — e.g. p95 0.4 vCPU → 0.5 vCPU, not 0.25 (too tight).
- Register a new task-definition revision and roll it out at low traffic, watching CPU throttling for 24–48 hours; bump a size if throttling is sustained.
- Tune headroom by task class — web/API 20% (autoscaling + LB smooth it), background/batch 10–15%, and don't cut spike-driven jobs (size them for the spike or split into their own task def, then rightsize the everyday tasks aggressively).
- Let Compute Optimizer do the first pass — its free Fargate recommendations are accurate; at 50+ tasks, automate the metrics→resize→deploy loop and re-check quarterly.
Gotchas
- Sizing to the average, not p95 is the classic over-cut — looks fine until the first normal traffic bump throttles tasks.
- Fixed CPU/memory combos mean dropping one dimension can force the other up or down — check both before deploying.
- Rightsize-once-and-forget decays — traffic and code drift, so a March-right task is often wrong by August.
- Skipping staging tests for critical services bites when the service has CPU-tied autoscaling triggers.
Skip this if
- Every task already sits near its provisioned limits at p95 — there's no fat to cut (rare, but verify before assuming).
- The win is really task count, not per-task size — pair with ECS Service Auto Scaling to drop replicas in quiet hours. Let Compute Optimizer generate the recommendations across the fleet, and cut the per-task rate on background workers with Fargate Spot.