RDS DB instances should have multiple AZ enabled
A single-AZ RDS instance goes completely offline when its host fails or the AZ has an outage. Multi-AZ keeps a synchronous standby in a different AZ that AWS promotes automatically, typically completing failover in under two minutes.
The cost is real: Multi-AZ roughly doubles instance cost because AWS runs a second instance. For production databases backing revenue-generating workloads, that trade-off is obvious. For dev/test environments, you may want to explicitly exclude them from this control or accept the finding.
Retrofit consideration
Enabling Multi-AZ on an existing single-AZ instance triggers a modification that may cause a brief I/O suspension (typically under 60 seconds) while the standby is provisioned and initial sync completes. Apply during a maintenance window. Instance costs will approximately double.
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 "rds" {
source = "hipaa.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "nist80053.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "nistcsf.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "fedrampmoderate.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "cis.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "nist800171.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "cisacyberessentials.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "nydfs23.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "cisv500.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "ffiec.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "cccsmedium.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "acscism2023.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "cfrpart11.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "rbiitfnbfc.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "fedramplow.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "hipaasecurity2003.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "nistcsfv11.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
module "rds" {
source = "nist80053rev4.compliance.tf/terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
}
If you use terraform-aws-modules/rds/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 "rds" {
source = "terraform-aws-modules/rds/aws"
version = ">=7.0.0"
allocated_storage = 20
db_name = "myapp"
db_subnet_group_name = "example-db-subnet-group"
engine = "mysql"
engine_version = "8.0.41"
family = "mysql8.0"
identifier = "abc123"
instance_class = "db.t3.micro"
major_engine_version = "8.0"
password_wo = "change-me-in-production"
skip_final_snapshot = true
username = "dbadmin"
vpc_security_group_ids = ["sg-12345678"]
multi_az = true
}
Use AWS provider resources directly. See docs for the resources involved: aws_db_instance.
resource "aws_db_instance" "this" {
allocated_storage = 20
enabled_cloudwatch_logs_exports = ["general", "slowquery"]
engine = "mysql"
identifier = "pofix-abc123"
instance_class = "db.t3.micro"
monitoring_interval = 60
monitoring_role_arn = "arn:aws:iam::123456789012:role/example-role"
password = "ChangeMe123!"
skip_final_snapshot = true
username = "dbadmin"
multi_az = true
}
What this control checks
The control checks whether aws_db_instance has multi_az = true. Omitting the argument defaults it to false, which fails. Aurora handles Multi-AZ differently: you distribute aws_rds_cluster_instance resources across AZs rather than setting a flag on aws_db_instance. This control targets standalone non-Aurora engines: MySQL, PostgreSQL, MariaDB, Oracle, and SQL Server. Set multi_az = true explicitly in your aws_db_instance block.
Common pitfalls
Terraform default is false
Omit
multi_azfromaws_db_instanceand it silently defaults tofalse. Any module or resource block without an explicitmulti_az = truefails this control, regardless of what the developer assumed about the default.Read replicas are not Multi-AZ standby
An
aws_db_instancecreated withreplicate_source_dbis a read replica, not a Multi-AZ standby. Read replicas use asynchronous replication and do not provide automatic failover. You still needmulti_az = trueon the primary instance.Aurora clusters handled differently
Aurora achieves Multi-AZ by placing
aws_rds_cluster_instanceresources in different AZs using theavailability_zoneargument. Themulti_azflag onaws_db_instancedoes not apply to Aurora, so this control may not evaluate Aurora clusters correctly.Applying to an existing instance causes an I/O pause
Use
apply_immediately = falseto defer the change to the next maintenance window. Flippingmulti_azfromfalsetotrueon a live instance triggers an in-place modification: AWS takes a snapshot, provisions the standby, and synchronizes. There can be brief I/O suspension during initial sync.Cost doubles for every enabled instance
Multi-AZ provisions a second instance of the same class. A
db.r6g.xlargeat roughly $0.48/hr becomes ~$0.96/hr. Exclude dev and staging environments from enforcement, or budget for them explicitly before rolling this out.
Audit evidence
An auditor will look for AWS Config evaluations showing all RDS instances pass the rds-multi-az-support managed rule. The RDS Console's "Configuration" tab for each instance should show "Multi-AZ: Yes". Programmatic evidence comes from aws rds describe-db-instances filtered on the MultiAZ field. CloudTrail ModifyDBInstance events with MultiAZ parameter changes document when remediation occurred.
For periodic reviews, a compliance report from Security Hub or a CSPM tool listing all RDS instances and their Multi-AZ status is a point-in-time snapshot that can be attached to the control assessment.
Framework-specific interpretation
HIPAA Omnibus Rule 2013: 45 CFR 164.308(a)(7) requires covered entities to implement data backup and disaster recovery procedures as part of their contingency plan. Multi-AZ keeps a synchronous standby in a separate AZ with automatic promotion, directly supporting availability for systems storing ePHI.
NIST SP 800-53 Rev 5: A synchronous standby in a separate AZ satisfies the alternate storage site intent of CP-6 and supports automated recovery under CP-10 without manual intervention.
NIST Cybersecurity Framework v2.0: Multi-AZ supports CSF 2.0 Protect outcomes around infrastructure resilience, specifically the expectation that services remain available through AZ-level disruptions.
FedRAMP Moderate Baseline Rev 4: At the Moderate baseline, CP-10 expects federal systems to recover from disruptions with minimal data loss. Multi-AZ synchronous replication can provide very low RPO for the database tier. FedRAMP assessors will look for evidence this is enabled on production databases.
Related controls
FSx for NetApp ONTAP file systems should be configured for Multi-AZ deployment
SageMaker endpoint production variants should have an initial instance count greater than 1
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
rds_db_instance_multiple_az_enabledAWS Config Managed Rule:
RDS_MULTI_AZ_SUPPORTCheckov Check:
CKV_AWS_157Powerpipe Control:
aws_compliance.control.rds_db_instance_multiple_az_enabledProwler Checks:
rds_cluster_multi_az,rds_instance_multi_azAWS Security Hub Control:
RDS.5
Last reviewed: 2026-03-09