Compute Optimizer is a fine starting point for EC2 rightsizing, but it only sees what CloudWatch sees — and by default CloudWatch does not see memory. In practice, real rightsizing is a three-step exercise: get memory telemetry installed so recommendations stop being CPU-only guesses, overlay what the tool cannot know (burst credits, license terms, JVM heaps, failover headroom), and then downsize one instance at a time with a fast path back. The tool proposes; the operator disposes.
What’s happening
Compute Optimizer analyzes CloudWatch utilization history — 14 days by default, up to 93 days if you pay for enhanced infrastructure metrics — and recommends instance types with better fit. We covered the tool itself in Compute Optimizer rightsizing; this article is about the gap between its recommendation and a safe change.
The gaps that matter in production. First, memory is invisible without the CloudWatch agent: an instance at 20% CPU and 92% RAM looks like a downsizing candidate to any CPU-only analysis, and shrinking it produces an OOM-killing incident, not a saving. Second, burstable instances lie at a glance: a t3.large at 15% average CPU may be living off CPU credits, and the “obvious” move to a smaller t3 collapses when credits run out. Third, the tool does not know your application: a JVM with a fixed 12 GB heap, a vendor license priced per core, a node deliberately sized to absorb a partner node’s failover — all look like waste in a utilization graph. Fourth, lookback windows miss slow cycles: month-end closes, seasonal peaks, an annual audit batch. A 14-day window in mid-July knows nothing about January.
What to check first
- Is the CloudWatch agent deployed? If there is no
CWAgentnamespace in CloudWatch metrics, every recommendation you have is CPU/network-only. Fix this before acting on anything. - Which instances are burstable? Anything in the T family needs its credit balance examined, not just its CPU average.
- What generation are you on? An
m4orm5at healthy utilization still costs more than the equivalent current-generation instance; same-size generation upgrades are the lowest-risk saving available. - Are the candidates in an Auto Scaling group? Then rightsizing means editing the launch template and letting rotation do the work — a different, safer procedure than resizing pets.
- What is the peak, not the average? Pull p95/max over 90 days, not the 2-week mean.
How to verify
# Compute Optimizer's current view
aws compute-optimizer get-ec2-instance-recommendations \
--query 'instanceRecommendations[].[instanceArn,finding,currentInstanceType,recommendationOptions[0].instanceType]' \
--output table
# Peak CPU over 90 days, daily maximums — not the average
aws cloudwatch get-metric-statistics --namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
--start-time 2026-04-05T00:00:00Z --end-time 2026-07-04T00:00:00Z \
--period 86400 --statistics Maximum
# Memory, if the CloudWatch agent is reporting
aws cloudwatch get-metric-statistics --namespace CWAgent \
--metric-name mem_used_percent \
--dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
--start-time 2026-06-04T00:00:00Z --end-time 2026-07-04T00:00:00Z \
--period 3600 --statistics Maximum
# Burst credit balance for T-family instances
aws cloudwatch get-metric-statistics --namespace AWS/EC2 \
--metric-name CPUCreditBalance \
--dimensions Name=InstanceId,Value=i-0123456789abcdef0 \
--start-time 2026-06-27T00:00:00Z --end-time 2026-07-04T00:00:00Z \
--period 3600 --statistics Minimum
Console paths: EC2 > Instances > Monitoring for per-instance graphs, Compute Optimizer > EC2 instances for the findings list. A credit balance that trends toward zero during business hours disqualifies a T-family downsize. The instance-type change mechanics are in the EC2 documentation.
The runbook
- Deploy the CloudWatch agent fleet-wide first. Via SSM Distributor or your config management, with
mem_used_percentat minimum. Then wait two weeks — acting on CPU-only data is how rightsizing gets its bad reputation. - Take the free wins: generation upgrades. Same size, newer family (
m5.xlargetom7g.xlargewhere ARM is viable, orm7i.xlargewhere it is not) cuts cost at equal or better performance with no capacity risk. Check Graviton compatibility separately — that is a port decision, not a resize. - Downsize the clear cases one step at a time. Candidates with p95 CPU under ~30% and p95 memory under ~50% over 90 days drop one size, never two. Stop, change instance type, start — this is minutes of downtime for a standalone instance, so schedule it; for ASG-managed fleets, update the launch template and roll.
- Watch each change for a full business cycle. CPU, memory, and the application’s own latency metrics for at least a week — including whatever weekly batch the instance secretly runs.
- Handle burstables explicitly. If a T instance burns credits daily, it is undersized regardless of its average; move it up or to a fixed-performance family. If it never touches credits, it may be a candidate for one size down.
- Document the exceptions. Instances kept large for heap, license, or failover reasons get a tag saying so — otherwise next quarter’s hunt re-litigates the same instances.
When this is the wrong move
Do not rightsize during or right before your peak season; the savings are permanent but so are the incident reports. Skip instances slated for containerization or replacement within the quarter — the effort is better spent on the migration. And in an Auto Scaling group whose policies already track utilization, aggressive per-instance shrinking mostly just increases instance count; tune the group’s scaling target instead.
Common mistakes
- Trusting a downsize recommendation computed without memory metrics.
- Resizing two sizes down in one jump because the graphs looked flat — the failure mode is nonlinear.
- Ignoring EBS bandwidth and network baseline: smaller instances get smaller EBS throughput and network allowances, which can bottleneck an I/O-heavy workload whose CPU was idle.
- Rightsizing the instance but not the commitment plan — shrink first, then size your Savings Plan floor, in that order.
Prevention
- Keep the CloudWatch agent in every AMI or launch template so memory data always exists.
- Run a quarterly rightsizing review with a 90-day lookback; small regular passes beat annual purges.
- Enforce current-generation instance types in new launch templates.
- Record sizing rationale in tags (
sizing:reason=jvm-heap-12g) to make future reviews fast. - Track the fleet-wide p95 utilization as a KPI so drift is visible before the bill says so.
Rightsizing is not a tool output; it is a habit with telemetry behind it. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.