EC2 instances should have detailed monitoring enabled
Basic monitoring at 5-minute intervals creates blind spots for anomaly detection and incident response. A CPU spike or network saturation event can begin and resolve within that window, leaving no trace in metrics. Detailed monitoring at 1-minute granularity gives CloudWatch alarms enough resolution to trigger on real operational events rather than averaged-out noise.
Detailed monitoring adds per-instance CloudWatch charges (region-dependent), but the observability gain shows up across auto-scaling decisions, performance troubleshooting, and security event correlation. Without it, you're making capacity and incident decisions on stale data.
Retrofit consideration
Enabling detailed monitoring on running instances causes no downtime, but each instance will begin incurring the additional CloudWatch detailed monitoring charge immediately.
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 = "pcidss.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 = "nistcsf.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 = "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 = "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 = "acscessentialeight.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 = "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 = "nist80053rev4.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"
monitoring = 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"]
monitoring = true
}
What this control checks
The control checks that aws_instance has monitoring set to true. Terraform defaults this to false, so omitting the argument means basic 5-minute monitoring. Set monitoring = true explicitly on every aws_instance to pass. For instances launched from an aws_launch_template, the equivalent is monitoring { enabled = true } inside the launch template; that setting propagates to all instances it creates. Any instance with monitoring absent or false fails.
Common pitfalls
Launch templates override instance-level settings
If instances are created via an Auto Scaling Group referencing an
aws_launch_template, themonitoringargument on anyaws_instanceresource is irrelevant. Setmonitoring { enabled = true }inside theaws_launch_templateresource instead. Instances launched from a template without this block default to basic monitoring.Default is false, not true
Omit the
monitoringargument onaws_instanceand you get basic monitoring silently. This is a common miss in modules that don't explicitly expose or default themonitoringvariable.Spot and ephemeral instances may be excluded
Spot instances launched outside of Terraform (e.g., by EMR clusters or Batch compute environments) won't inherit your Terraform-managed
monitoring = truesetting. These instances still appear in Config evaluations and will flag as non-compliant.Cost accumulation at scale
Detailed monitoring charges accumulate per instance and vary by region. At fleet scale, this can become a meaningful monthly cost and should be budgeted explicitly. The charge applies per instance, not per metric.
Audit evidence
Config rule ec2-instance-detailed-monitoring-enabled evaluation results showing all instances as COMPLIANT are the most direct evidence. CLI output from aws ec2 describe-instances filtered to Monitoring.State works too; every running instance should return enabled, not disabled. For bulk coverage across accounts and regions, a Config advanced query or aggregator export covers both.
For continuous proof, a conformance pack that includes this rule with historical compliance timelines showing no drift is what most auditors ask to see.
Framework-specific interpretation
SOC 2: CC7.2 calls for anomaly detection on system components. Detailed monitoring gives CloudWatch alarms 1-minute data points to fire on, which is what satisfies that criterion in practice.
PCI DSS v4.0: For instances in the cardholder data environment, Requirement 10 mandates timely detection of anomalies across system components. Detailed monitoring is one piece of that picture, alongside required log monitoring controls. Basic 5-minute intervals leave gaps that examiners will ask about.
HIPAA Omnibus Rule 2013: 45 CFR 164.312(b) requires audit controls on systems handling ePHI. Performance anomalies and potential security events on EC2 instances processing health data need enough time resolution to be investigable after the fact. One-minute intervals provide that; basic monitoring often doesn't.
NIST Cybersecurity Framework v2.0: DE.CM expects continuous monitoring of compute resources. One-minute granularity is what makes CloudWatch alarms actionable against that expectation.
FedRAMP Moderate Baseline Rev 4: CA-7 and SI-4 both call for continuous monitoring capabilities. At the Moderate baseline, that means metric data granular enough to detect and respond to events within expected timeframes. One-minute CloudWatch metrics meet that bar; 5-minute averages generally don't.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
ec2_instance_detailed_monitoring_enabledAWS Config Managed Rule:
EC2_INSTANCE_DETAILED_MONITORING_ENABLEDCheckov Check:
CKV_AWS_126Powerpipe Control:
aws_compliance.control.ec2_instance_detailed_monitoring_enabledProwler Check:
ec2_instance_detailed_monitoring_enabledKICS Query:
23b70e32-032e-4fa6-ba5c-82f56b9980e6
Last reviewed: 2026-03-09