Overview

EC2 Rules

CloudBurn cost optimization rules for AWS EC2.


EC2 Rules

These rules identify EC2 instances using outdated types, idle or oversized instances, unassociated Elastic IPs, unused VPC endpoints, expiring Reserved Instances, and long-running instances that may benefit from a generational refresh.

Rule IDScan TypeName
CLDBRN-AWS-EC2-1Discovery and IaCEC2 Instance Type Not Preferred
CLDBRN-AWS-EC2-2IaCS3 Interface VPC Endpoint Used
CLDBRN-AWS-EC2-3DiscoveryElastic IP Address Unassociated
CLDBRN-AWS-EC2-4DiscoveryVPC Interface Endpoint Inactive
CLDBRN-AWS-EC2-5DiscoveryEC2 Instance Low Utilization
CLDBRN-AWS-EC2-9DiscoveryEC2 Instance Without Graviton
CLDBRN-AWS-EC2-10DiscoveryEC2 Reserved Instance Expiring
CLDBRN-AWS-EC2-11DiscoveryEC2 Instance Large Size
CLDBRN-AWS-EC2-12DiscoveryEC2 Instance Long Running

CLDBRN-AWS-EC2-1

EC2 Instance Type Not Preferred

Scan type: Discovery and IaC

What it checks

Flags EC2 instances not using the curated set of preferred instance families. The preferred families are c8, m8, r8, and t4g — current-generation types offering the best price/performance available on EC2 today.

Why it matters

Older instance families (c1–c7, m1–m7, r3–r7, t1–t3a) are less efficient, often more expensive, and in some cases on a deprecation path. Current-generation Graviton4 instances (m8g, c8g, r8g) provide 30-40% better performance per dollar than the previous generation at the same or lower price.

What triggers a finding

The instance family is in the non-preferred list: c1, c3, c4, c5, c5a, c5n, c6a, c6g, c6i, c6in, c7a, c7g, c7i, m1, m2, m3, m4, m5, m5a, m5n, m5zn, m6a, m6g, m6i, m6in, m7a, m7g, m7i, r3, r4, r5, r5a, r5n, r6a, r6g, r6i, r6in, r7a, r7g, r7i, t1, t2, t3, t3a.

How to remediate

Migrate to the equivalent preferred family:

  • c* family → c8g (e.g., c6i.largec8g.large)
  • m* family → m8g (e.g., m6i.xlargem8g.xlarge)
  • r* family → r8g (e.g., r6i.2xlarger8g.2xlarge)
  • t2/t3/t3at4g

Test your workload with the new instance type in a non-production environment first, particularly if migrating from x86 to Graviton (arm64).

IaC resources checked

IaC ToolResource Type
Terraformaws_instance
CloudFormationAWS::EC2::Instance

CLDBRN-AWS-EC2-2

S3 Interface VPC Endpoint Used

Scan type: IaC

What it checks

Flags VPC endpoints for S3 that are configured as Interface type. S3 has a free Gateway endpoint option that provides the same access within a VPC without any hourly or data-processing charges.

Why it matters

A VPC Interface endpoint for S3 costs approximately $0.01/hour per AZ (~$7/month per AZ) plus $0.01/GB processed. A three-AZ deployment costs $21+/month just in endpoint hours. The S3 Gateway endpoint is free and functionally equivalent for most use cases — it does not traverse the internet and does not require a NAT gateway.

What triggers a finding

A VPC endpoint resource has a serviceName ending in .s3 AND a VpcEndpointType (or type) of Interface.

How to remediate

Replace the S3 Interface endpoint with a Gateway endpoint:

# Replace this:
resource "aws_vpc_endpoint" "s3_interface" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type = "Interface"
}

# With this:
resource "aws_vpc_endpoint" "s3_gateway" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [aws_route_table.main.id]
}

IaC resources checked

IaC ToolResource Type
Terraformaws_vpc_endpoint
CloudFormationAWS::EC2::VPCEndpoint

CLDBRN-AWS-EC2-3

Elastic IP Address Unassociated

Scan type: Discovery

What it checks

Flags Elastic IP addresses not associated with any resource. Unassociated EIPs incur a charge that was introduced by AWS in February 2024 to encourage cleanup of unused addresses.

Why it matters

As of February 2024, AWS charges $0.005/hour (~$3.65/month) for every Elastic IP that is not associated with a running instance. An account with 10 unassociated EIPs pays $36.50/month with no benefit.

What triggers a finding

The EIP has no associationId, instanceId, or networkInterfaceId.

How to remediate

Release unassociated EIPs:

aws ec2 release-address --allocation-id eipalloc-0abc1234def56789

If you need to preserve the IP address for future use, note that AWS does not guarantee that a released IP will be available to re-allocate. Plan accordingly before releasing.


CLDBRN-AWS-EC2-4

VPC Interface Endpoint Inactive

Scan type: Discovery

What it checks

Flags VPC Interface endpoints that processed zero bytes in the past 30 days. An endpoint with no traffic is not serving any workload but continues to incur hourly charges for each Availability Zone it is provisioned in.

Why it matters

Each VPC Interface endpoint AZ costs approximately $0.01/hour (~$7/month per AZ). An endpoint active across 3 AZs costs ~$21/month. An endpoint that has processed no traffic in 30 days is almost certainly unused.

What triggers a finding

bytesProcessedLast30Days is 0.

How to remediate

Delete the inactive VPC endpoint:

aws ec2 delete-vpc-endpoints --vpc-endpoint-ids vpce-0abc1234def56789

Before deleting, verify no application is using the endpoint by checking security group rules and DNS resolution for the endpoint service name. An endpoint can show zero bytes if traffic recently stopped but the endpoint is still referenced.


CLDBRN-AWS-EC2-5

EC2 Instance Low Utilization

Scan type: Discovery

What it checks

Flags EC2 instances with consistently low CPU and network utilization. Instances running at very low utilization are likely oversized for their workload or are no longer actively used.

Why it matters

An oversized EC2 instance pays for compute capacity that is not being used. A m7i.4xlarge idling at 2% CPU costs ~$550/month and could potentially be replaced by a m7i.large at ~$70/month — an 87% reduction for the same workload.

What triggers a finding

lowUtilizationDays is 4 or more out of the past 14 days. A day is counted as low-utilization when both CPU and network metrics are below their respective thresholds.

How to remediate

  • Rightsize the instance to a smaller type that matches actual utilization
  • If the instance is a dev/test server, schedule it to stop outside working hours
  • If the instance hosts a workload that would fit on Lambda or containers, consider migrating to reduce the minimum footprint
  • Use AWS Compute Optimizer recommendations as a starting point for rightsizing decisions

CLDBRN-AWS-EC2-9

EC2 Instance Without Graviton

Scan type: Discovery

What it checks

Flags EC2 instances not using the arm64 architecture when a Graviton equivalent exists for the instance family. This rule covers a broader set of instances than CLDBRN-AWS-EC2-1, specifically targeting the Graviton migration opportunity regardless of generation.

Why it matters

Graviton instances (arm64) typically offer 20-40% better price/performance than equivalent x86 instance types. Moving to Graviton is often the single highest-impact optimization available for compute-heavy workloads.

What triggers a finding

The instance architecture is not arm64 AND the instance family is in the Graviton review set (families that have a direct Graviton equivalent).

How to remediate

  1. Identify the Graviton equivalent for your instance family (e.g., m6im6g, c6ic6g, or migrate all the way to m8g/c8g)
  2. Verify your software stack runs on arm64 — check language runtime support, native libraries, and container image architectures
  3. Test in a non-production environment, then migrate production using a stop-change-start or blue/green approach

CLDBRN-AWS-EC2-10

EC2 Reserved Instance Expiring

Scan type: Discovery

What it checks

Flags active EC2 Reserved Instances that expire within 60 days. An expiring RI that covers a running instance will revert to On-Demand pricing on expiration, potentially causing a significant cost increase.

Why it matters

RIs provide up to 72% discount compared to On-Demand. When an RI expires, the covered instance immediately starts billing at the full On-Demand rate. For a production instance, this can mean hundreds of dollars per month in unexpected charges if the expiration is not handled proactively.

What triggers a finding

The RI state is active AND the endTime is within 60 days from today.

How to remediate

Review each expiring RI and decide:

  • Renew: Purchase a new RI for the same instance type and term
  • Exchange: Use RI Convertible exchanges to change to a different instance type before expiration if your instance type needs have changed
  • Switch to Savings Plans: Compute Savings Plans are more flexible than RIs and often a better long-term strategy
  • Let expire: If the instance will be decommissioned before the RI expires, no action needed

CLDBRN-AWS-EC2-11

EC2 Instance Large Size

Scan type: Discovery

What it checks

Flags EC2 instances sized 2xlarge or larger, including metal instances. Large instances are significantly more expensive than smaller ones and should be reviewed regularly to confirm the size is justified.

Why it matters

Large instances can cost 4–64x as much as smaller equivalents. A m7i.16xlarge costs ~$2,400/month vs ~$150/month for a m7i.large. While large sizes are sometimes necessary, they are also commonly over-provisioned — sized for a peak load that never materializes or left over from an early sizing decision that was never revisited.

What triggers a finding

Instance size suffix is 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge, 24xlarge, 32xlarge, 48xlarge, or metal.

How to remediate

  • Review CloudWatch CPU, memory (from CloudWatch Agent), and network metrics for the past 30 days
  • If utilization is consistently low, downsize to the next smaller type
  • Consider Savings Plans if the instance will remain large — Compute Savings Plans apply to any size or family

CLDBRN-AWS-EC2-12

EC2 Instance Long Running

Scan type: Discovery

What it checks

Flags EC2 instances that have been running continuously for 180 or more days. Long-running instances may be using outdated instance types, missing the opportunity for newer-generation cost improvements, or running workloads that could be better served by auto-scaling or managed services.

Why it matters

EC2 instance generations improve approximately every 2 years. An instance running for 6+ months on a previous generation is likely paying more than necessary compared to a current-generation equivalent. Long-running instances are also less likely to be rightsized since they were provisioned once and never revisited.

What triggers a finding

Instance state is running AND launchTime is 180 or more days ago.

How to remediate

Use this finding as a prompt for a regular instance review:

  1. Check whether the instance type is still the best fit (instance family, size, generation)
  2. Review utilization to confirm the size is appropriate
  3. Check whether a Reserved Instance or Savings Plan covers this instance
  4. If the instance runs a stateless workload, consider replacing it with an auto-scaling group so instances refresh naturally on AMI or type changes

See Also