Just moved to AWS? What to check in your first month
A lift-and-shift copies on-premises habits into a bill that charges by the hour. Seven things to check in the first 30 days after a migration.

A lift-and-shift moves your servers to AWS more or less as they were. That is the point of it. It gets you out of the data center quickly.
It also moves the habits that came with the servers. On premises, a server sized for peak load costs the same whether it is busy or not, because you already bought the hardware. On AWS it keeps billing for every hour it exists.
So the first month after a migration is a good time for a short review. This post is a checklist. Each item says what to look for, why it costs money, and which CloudWise check covers it.
Why the first month
The bill does not tell you what is wrong. It tells you what you spent. The people who sized the servers have often moved on to the next project, and nobody has a baseline yet for what normal looks like.
Migration also leaves things behind. Volumes, snapshots and images were created along the way, and the migration plan rarely included deleting them.
Where the checks come from
Each check below is in the open-source CLI, so it runs on your machine with read-only credentials. Every check has a validation level. Level 2 means the check fired on a real test resource and stayed quiet on a matching control. We only call a check proven when it has reached level 2 or higher and its review found nothing left to fix. The waste checks page shows the current level for every check.
1. Servers that run but do nothing
What to look for. Instances that are running and doing almost no work. Servers sized for the busiest day of the year often sit near idle the rest of the time.
Why it costs money. An EC2 instance bills while it is running, whatever its CPU is doing.
The check. idle_ec2 flags instances with an average CPU below 5% over 14 days and no sustained or heavy peaks. It skips instances that belong to Auto Scaling groups, EKS, Elastic Beanstalk, EMR, Spot Fleet and EC2 Fleet, and instances younger than the 14-day window. It is not on the proven list yet, so treat a finding as a lead. CPU alone says nothing about memory, disk or network. Ask the owner before you resize or stop anything.
Two weeks of data is also the limit. A server that only matters at quarter end can look idle in the first month.
2. Stopped servers that still pay for disks
What to look for. Instances you stopped after cutover "just in case".
Why it costs money. A stopped instance does not bill for compute, but its EBS volumes keep billing. See the EC2 instance lifecycle.
The check. stopped_ec2_with_ebs (proven, level 3) lists stopped instances and prices each attached volume by its real size and type. Before you delete anything, read what to check before you delete a finding.
3. Volumes attached to nothing
What to look for. EBS volumes in the available state. Migration tools create volumes, and a failed or repeated cutover can leave some behind.
Why it costs money. EBS charges for the storage you provision, whether or not an instance uses it. See EBS pricing.
The check. unattached_ebs (proven, level 3) finds volumes attached to nothing.
4. Snapshots and images nobody needs
What to look for. Snapshots from the migration, and snapshots left after you deregistered the images they backed.
Why it costs money. Deregistering an AMI does not delete its snapshots. In AWS's words, "any snapshots not deleted will continue to incur storage costs." See deregistering an AMI.
The checks. orphaned_ebs_snapshot (proven, level 2) finds snapshots whose source volume was deleted. ami_orphaned_snapshot (proven, level 2) finds snapshots whose image was deregistered. A third check, old_ebs_snapshot, flags snapshots at least 90 days old, and never the newest snapshot of a volume that still exists. It is level 1, so it is not proven, and a first-month migration will not have 90-day-old snapshots yet. Put it on the calendar for month four.
Be careful here. A snapshot may be the only backup of something. Confirm that before you delete it. To keep a snapshot on purpose, tag it cloudcostwise:keep (any value) or DoNotDelete=true, and all three snapshot checks skip it.
5. Public IPv4 addresses and idle Elastic IPs
What to look for. Elastic IPs that are attached to nothing, or attached to stopped instances.
Why it costs money. AWS charges $0.005 per hour for an Elastic IP that sits idle. Since 1 February 2024 it also charges that rate for every public IPv4 address in use. See AWS's announcement. An on-premises address block did not bill this way, so this one surprises people.
The checks. unattached_eip (proven, level 4) finds addresses attached to nothing. eip_on_stopped_instance (proven, level 3) finds addresses held by stopped instances. Releasing an Elastic IP cannot be undone, because a new address would be a different IP, so update any DNS records or allowlists first.
6. NAT gateways with no traffic
What to look for. NAT gateways that were set up to match the old network layout and now carry nothing.
Why it costs money. A NAT gateway bills for each hour it is available, plus data it processes. See the NAT gateway section of VPC pricing. The hourly part continues when traffic is zero.
The check. idle_nat_gateway (proven, level 2) flags gateways with no bytes transferred for 7 days. A seven-day window can miss a job that runs monthly, so check with the owner.
7. Load balancers with nothing behind them
What to look for. Load balancers whose targets were never registered, or were removed during cutover.
Why it costs money. Elastic Load Balancing bills for each hour a load balancer is running. See Elastic Load Balancing pricing.
The check. idle_load_balancer (proven, level 2) finds load balancers with no healthy targets, or healthy targets and no requests. Confirm that no DNS record still points at the load balancer before you remove it.
One more: volume type
Servers moved with older gp2 volumes often stay on them. gp2_migration finds those volumes. On current instance types, AWS lets you change a volume from gp2 to gp3 without detaching it, and it keeps at least the same performance when you do not set IOPS or throughput. See modifying a volume. It is at level 3 but not on the proven list yet. Check the volume's IOPS needs before you change it.
What this list does not cover
It does not cover right-sizing running servers by memory, always-on test environments, or licensing. A tool that reads only CPU cannot tell you those. The CLI's oversized_ec2_optimizer check reports what AWS Compute Optimizer recommends. It is level 1, so read it as AWS's opinion, not ours.
A 30-day routine
- Week 1: run the scan and sort the findings into "remove", "check first" and "keep on purpose".
- Week 2: remove the cheap, safe ones. Give each "check first" item an owner and a date.
- Week 4: run the scan again. Whatever is still on the list needs a decision.
- Put it on the calendar for next quarter. Waste builds one forgotten resource at a time.
Run it yourself
The CLI is free and open source (Apache-2.0). It runs on your machine, reads your AWS account with your own credentials, and sends nothing to CloudWise.
pip install cloudcostwise
cloudcostwise scan --profile my-profile --regions all
Read-only and free. AWS bills the scan's Cost Explorer calls; add --no-cost-explorer to skip them. Start at cloudcostwise.io.
Find this waste in your own account
Run the free scanner on your own machine. Read-only, no signup, and nothing is sent to CloudWise unless you choose to share a summary at the end.
$ pipx install cloudcostwise
What it checksPrefer a dashboard? Start a free hosted scan →