Chatwithcloud logo


AWS GenAI Tools

Detect and Stop Underutilized EC2 Instances Based on CPU Metric

Every instance running in your Amazon Web Services (AWS) environment costs you money, so it is important to stop instances that are idle or underutilized. The following piece of JavaScript (JS) code will allow you to detect AWS Elastic Compute Cloud (EC2) instances that are underutilized based on their CPU metrics.

The code integrates AWS SDK to interact with AWS services.


Here is the JavaScript code to identify and stop underutilized EC2 instances.

const AWS = require('aws-sdk'); const cloudwatch = new AWS.CloudWatch(); const ec2 = new AWS.EC2(); async function stopUnderutilizedInstances() { const instances = await ec2.describeInstances({ Filters: [{ Name: 'instance-state-name', Values: ['running'] }] }).promise() for (let instance of instances.Reservations[0].Instances) { const metrics = await cloudwatch.getMetricStatistics({ Namespace: 'AWS/EC2', MetricName: 'CPUUtilization', Dimensions: [{ Name: 'InstanceId', Value: instance.InstanceId }], StartTime: new Date(new Date().getTime() - 24 * 60 * 60 * 1000), EndTime: new Date(), Period: 3600, Statistics: ['Average'] }).promise() if (metrics.Datapoints[0].Average < 20.0) { await ec2.stopInstances({ InstanceIds: [instance.InstanceId] }).promise() console.log(`Stopped instance ${instance.InstanceId} due to underutilization`) } } } stopUnderutilizedInstances();

Detailed Code Explanation

The above piece of code first imports the "aws-sdk" module to interact with AWS services. We then create empty constructors for two AWS SDK objects namely "CloudWatch" and "EC2".

Within our stopUnderutilizedInstances function, we first retrieve all the instances which are currently running with status "Running". For each running instance, we then use CloudWatch to get the CPU utilization metrics for the last 24 hours (i.e., StartTime is set to 24 hours ago and EndTime to the current time).

If the average CPUUtilization of any instance is less than 20%, we stop that instance using the stopInstances EC2 method. Finally, a console.log is included for each instance stopped to confirm the action taken.

Expected Output Format

You can expect a string output on the console for each instance that gets stopped. The format will be:

"Stopped instance <instance-id> due to underutilization"

where <instance-id> is the ID of the EC2 instance.

Considerations & Caveats

While this allows to detect and stop underutilized EC2 instances based on the CPU metric, the 20% threshold is hardcoded, and it might not be suitable for all types of workloads. Be cautious of stopping instances that might have low CPU utilization but are still performing important tasks.

Do not forget this script only considers instances that have been running for at least 24 hours. One-time or short-duration instances would not be considered, so manage these separately.

Required IAM Permissions and Example Policy

The AWS user executing the script must have EC2:DescribeInstances, EC2:StopInstances and CloudWatch:GetMetricStatistics permissions. Here is a basic IAM policy with these permissions:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:StopInstances", "cloudwatch:GetMetricStatistics" ], "Resource": "*" } ] }


  1. What if I want to use a different CPU utilization threshold? - The threshold for CPU utilization can be modified by changing the value of 20.0 in the condition statement to the preferred threshold.
  2. Will this handle instances in all regions? - No, the current implementation handles instances in the EC2 region matching your AWS SDK configuration. To handle instances in all regions, iterate over different regions in your code.
  3. Can I use this for other types of resources on AWS? - This code only applies to EC2 instances. Other AWS services would require different metrics and APIs. Modifying the code to suit those resources would be necessary.
  4. Is the IAM policy provided above safe to use? - While the provided IAM policy is sufficient to run the script, it's always best practice to narrow down the wildcard resource "*" to specify only necessary resources for better security.

Related articles
Monitor and Notify When Approaching Service LimitsGet Current IAM Identity TypeScriptCalculate the Size of Each S3 Bucket and Find the One with the Most Data