EC2 instances should have EBS optimization enabled
Without EBS optimization, storage I/O shares bandwidth with regular network traffic on the instance. Under heavy load, this contention causes unpredictable latency spikes and throughput drops for both EBS volumes and network operations. Workloads that depend on consistent disk performance (databases, analytics pipelines, log aggregation) can experience degraded throughput that is difficult to diagnose because it correlates with unrelated network activity rather than storage load.
Many newer instance families (m5, c5, r5, and later generations) are EBS-optimized by default, but explicitly setting the flag ensures the behavior is intentional and survives instance type changes during refactoring.
Retrofit consideration
Enabling EBS optimization on older instance types (c3, m3, r3) may require a stop/start cycle and could change the instance's network throughput allocation. Verify your instance type supports EBS optimization before applying.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "ec2_instance" {
source = "soc2.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "hipaa.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "nist80053.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "fedrampmoderate.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "cisv80ig1.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "nist800171.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "awscontroltower.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "cisacyberessentials.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "nydfs23.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "eugmpannex11.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "cfrpart11.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "rbiitfnbfc.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "fedramplow.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "hipaasecurity2003.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "nistcsfv11.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
module "ec2_instance" {
source = "pcidssv321.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}
If you use terraform-aws-modules/ec2-instance/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
ebs_optimized = true
}
Use AWS provider resources directly. See docs for the resources involved: aws_instance.
resource "aws_instance" "this" {
ami = "ami-abc12345"
instance_type = "t4g.nano"
subnet_id = element(["subnet-abc123", "subnet-def456"], 0)
vpc_security_group_ids = ["sg-abc12345"]
ebs_optimized = true
}
What this control checks
This control validates that the aws_instance resource has ebs_optimized set to true. If omitted, plan state and the live API can diverge by instance type: newer families (m5, c5, r5, c6i, m6g, etc.) are EBS-optimized by default at the AWS level, but Terraform records the attribute as false when not explicitly set. The control expects the explicit argument regardless. Setting ebs_optimized = false fails; omission may also fail depending on whether the policy engine reads the configured value or the computed AWS state.
Common pitfalls
Instance types that do not support EBS optimization
Before setting
ebs_optimized = true, confirm the instance type supports it. Older types likem3.mediumwill return an API error duringterraform apply. Useaws ec2 describe-instance-types --filters Name=ebs-info.ebs-optimized-support,Values=supported,defaultto check, or consult the AWS instance type documentation.Default-optimized instances may still report false in state
Omit
ebs_optimizedon an m5 or c5, and AWS reportsEbsOptimized: trueat the API level while Terraform recordsfalsein state. Compliance tooling that reads Terraform state rather than the live AWS API will flag these instances as non-compliant even though the hardware is behaving correctly. Explicit is better.Launch templates override instance-level settings
If an
aws_launch_templateincludesebs_optimized, that setting takes precedence over what is on theaws_instanceresource. Setebs_optimized = truein theaws_launch_templateblock directly, not only on the instance definition.Cost implications on older generations
On some older instance families (c3, m3, r3), EBS optimization has historically carried a per-hour surcharge. Most current instance types include it at no extra cost, but check regional EC2 pricing before bulk-enabling across a fleet of legacy instances.
Audit evidence
AWS Config evaluation results for the ebs-optimized-instance managed rule are the primary artifact. Supporting evidence includes the EC2 console Instances view with the 'EBS optimized' column visible, or aws ec2 describe-instances output filtered on EbsOptimized: true for all running instances. For organizations running scheduled compliance scans, Config compliance timeline snapshots show sustained adherence across the audit period, not just a point-in-time screenshot.
Framework-specific interpretation
SOC 2: SOC 2 A1 (Availability) and related common criteria (CC3, CC7) call for infrastructure that maintains predictable performance under load. Shared I/O bandwidth is a source of availability risk; EBS optimization eliminates it.
HIPAA Omnibus Rule 2013: 45 CFR 164.312 requires covered entities to ensure the availability of ePHI systems. Storage I/O contention during peak load is a real availability risk, and for EC2 workloads, EBS optimization removes it.
NIST SP 800-53 Rev 5: Dedicated EBS throughput directly addresses SC-6 (Resource Availability) in NIST 800-53 Rev 5. Without it, a busy instance can saturate shared bandwidth and degrade both storage and network performance simultaneously, which is the resource contention scenario SC-6 controls are designed to prevent.
FedRAMP Moderate Baseline Rev 4: SC-6 requires federal systems to protect the availability of processing and communication resources. For EBS-backed workloads, dedicated I/O throughput is how you meet that requirement: shared-bandwidth contention under load is exactly the kind of resource exhaustion SC-6 is designed to prevent.
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
ec2_instance_ebs_optimizedAWS Config Managed Rule:
EBS_OPTIMIZED_INSTANCECheckov Check:
CKV_AWS_135Powerpipe Control:
aws_compliance.control.ec2_instance_ebs_optimizedKICS Query:
60224630-175a-472a-9e23-133827040766
Last reviewed: 2026-03-09