Idle AWS resources, found by metric and priced by region
- Running instances with negligible CPU and networkec2-idle
- Long-stopped instances still billing for storageec2-stopped
- GPU/accelerator instances with near-idle CPUgpu-idle
- RDS instances with zero connectionsrds-idle
- ElastiCache clusters with no client connectionselasticache-idle
- Redshift clusters with no database connectionsredshift-idle
- OpenSearch domains with no search or indexing trafficopensearch-idle
- NAT gateways with ~zero bytes processednat-idle
- Load balancers with no listeners or no healthy targetselb-half-connected
- Classic Load Balancers billed hourly with zero requests to zero healthy instancesclb-idle-zero-traffic
- EFS file systems with no client connections and no I/O over the lookbackefs-idle-filesystem
- Lambda functions with zero invocations in 30 dayslambda-idle
- EMR clusters alive and idle with auto-termination disabledemr-cluster-idle-waiting
- SageMaker endpoints with zero invocationssagemaker-endpoint-idle
Why idle resources are measured, not guessed
“Idle” is a claim about the last thirty days, and the only honest basis for it is the metrics AWS already records. Kostrix reads CloudWatch for each resource over a trailing window and applies a stated threshold, so every finding can be checked in your own console against the same graph.
The thresholds are the product's defaults, printed on every finding beside the measured value, for example “Average CPU 1.2% and 0.4 MB/day network over 30 days — below the idle thresholds (3% / 5 MB/day).” The EC2 ones can be tightened or loosened per account. A resource that is quiet but used, such as a bastion host or a warm standby, is a judgement for whoever owns it, which is why the finding carries the resource's tags and asks you to check with the tagged owner before stopping anything.
Where idle resources hide: the regions nobody opens
The console shows one region at a time. An instance left running in us-west-2 after a migration to ap-south-1, or a NAT gateway in eu-west-3 from a disaster-recovery rehearsal, is invisible from the region you work in and visible on the bill.
Kostrix scans every region enabled on the account unless you pin the list, describes each resource where it sits, and reads the metrics from that region. A finding is keyed by account, region, rule and resource, so two instances with the same id in two regions are two findings, and the monthly figure for each is the rate for its own region.
What is read, and what counts as idle
One resource type at a time: the metric the scanner reads, the default threshold, and what the finding carries so the decision can be made without opening another console.
Idle EC2 instances
ec2-idle- Reads
- CloudWatch CPUUtilization (average) and NetworkIn + NetworkOut (sum)
- Idle when
- below 3% CPU and below 5 MB a day of network, both at once, over the trailing window
A running instance whose average CPU is under three percent and whose network traffic adds up to less than five megabytes a day is doing nothing anyone is waiting for. Both conditions have to hold: a low-CPU box moving traffic is a proxy or a queue consumer, not an idle one. The finding carries the instance type and its monthly rate, the Availability Zone and subnet, the private and public addresses and the security groups, so the engineer who has to decide can see what it is attached to. Stopped instances are a separate check (ec2-stopped): they stop billing for compute but keep billing for every volume attached to them.
RDS databases with zero connections
rds-idle- Reads
- CloudWatch DatabaseConnections (average), AWS/RDS or AWS/DocDB namespace
- Idle when
- an average of exactly zero connections across the trailing window, with datapoints present
A database instance in the available state that no client has connected to for the whole window is billed for its instance class, its storage and its backups all the same. The finding names the endpoint, the engine and version, the class and its monthly rate, the allocated storage and whether it is Multi-AZ, and recommends a final snapshot before deletion. A stopped RDS instance is not a remedy on its own: AWS restarts it after seven days, which is how idle databases quietly keep billing. DocumentDB instances surface through the RDS API but publish metrics under a different namespace, and the rule reads the right one.
NAT gateways moving no bytes
nat-idle- Reads
- CloudWatch BytesOutToDestination (sum)
- Idle when
- under one megabyte processed over the whole trailing window
A NAT gateway bills an hourly charge for every hour it exists, plus a per-gigabyte fee on what passes through it. One left behind in a subnet whose instances have moved on, or in a VPC a proof of concept ran in, moves nothing and still costs the hourly charge every month. The finding shows the VPC and subnet, the bytes processed over the window and the Elastic IPs associated with the gateway, and the checklist asks you to confirm no route table still points at it and no occasional batch job depends on it before you delete.
Load balancers with no healthy targets
elb-half-connected- Reads
- DescribeListeners, DescribeTargetGroups and DescribeTargetHealth, not a metric
- Idle when
- no listeners configured, no registered targets, or zero healthy targets
An Application or Network Load Balancer bills by the hour whether or not it can serve a request. One with no listener, no registered target or no healthy target cannot, so the state alone is the finding: it is read from the load balancer's own configuration and target health rather than inferred from traffic. The finding reports the type and scheme, the VPC and Availability Zones, the DNS name, the counts of listeners, registered and healthy targets, and the monthly base charge, and asks you to check DNS records and in-progress deployments before deleting. Classic Load Balancers with zero requests to zero healthy instances are a separate check (clb-idle-zero-traffic).
No datapoints is not zero utilization
Every idle check depends on a metric read, and a metric read can fail: a throttled CloudWatch region, a resource too new to have datapoints, a namespace that is not the one expected. Kostrix treats each of those as a gap, not as a reading of zero.
A resource with no datapoints is skipped, not flagged. A failed read is recorded against the rule and the region, so the scan reports “examined, with gaps” rather than “examined, clean”. The alternative, writing 0% where nothing was measured, would invent an idle fleet and a saving to go with it, and that saving would be the first number a finance team checked and the last one they trusted.
| Region | Mean CPU |
|---|---|
| ap-south-1 | 4.1% |
| eu-west-1 | 11.7% |
| eu-north-1 | no measurement |
The 14 idle-resource checks Kostrix runs
Each one is a rule in the scanner with the identifier it stamps on its findings. The wording is the rule's own description.
- ec2-idle
- Running instances with negligible CPU and network
- ec2-stopped
- Long-stopped instances still billing for storage
- gpu-idle
- GPU/accelerator instances with near-idle CPU
- rds-idle
- RDS instances with zero connections
- elasticache-idle
- ElastiCache clusters with no client connections
- redshift-idle
- Redshift clusters with no database connections
- opensearch-idle
- OpenSearch domains with no search or indexing traffic
- nat-idle
- NAT gateways with ~zero bytes processed
- elb-half-connected
- Load balancers with no listeners or no healthy targets
- clb-idle-zero-traffic
- Classic Load Balancers billed hourly with zero requests to zero healthy instances
- efs-idle-filesystem
- EFS file systems with no client connections and no I/O over the lookback
- lambda-idle
- Lambda functions with zero invocations in 30 days
- emr-cluster-idle-waiting
- EMR clusters alive and idle with auto-termination disabled
- sagemaker-endpoint-idle
- SageMaker endpoints with zero invocations
Idle is one family of waste among several. The full list of 235 AWS cost optimization checks covers the rest: unattached storage, over-provisioned capacity, migration candidates, and the governance checks that catch spend in regions where the account holds nothing. Unused EBS volumes and orphaned snapshots have a page of their own.
Delete unattached EBS volumes
2,113 volumes · ap-south-1 · $2,704.64/month
1 decision
Findings pool by the action they require
Forty idle instances in one region that all want stopping arrive as one priced line, with the count and the monthly figure, and the individual instances listed underneath for the engineer who has to act. The same pooling turns 2,113 unattached volumes into one decision.
Read-only, by construction
