Overview
This guide covers Multi-AZ RDS clusters, which use the standard mysql or postgres engine — not the Aurora engines (aurora-mysql or aurora-postgresql). The configuration, instance types, and storage model differ significantly from Aurora clusters.
A Multi-AZ DB cluster (distinct from a Multi-AZ DB instance) is a semi-synchronous high-availability deployment that places a writer and two readable standby instances across three separate Availability Zones. Unlike Aurora, this mode uses local storage attached to each instance, making allocated_storage, iops, and storage_type required configuration.
This module supports Multi-AZ RDS clusters using the same terraform-aws-modules/rds-aurora/aws source. The key difference is how the module detects which mode you want:
Setting allocated_storage to a non-null value is what switches the module into Multi-AZ RDS cluster mode. When allocated_storage is set, the module assigns cluster_instance_class to the db_cluster_instance_class attribute of the underlying aws_rds_cluster resource. Without allocated_storage, instances are managed separately as Aurora cluster instances. See the upstream discussion for details on why this proxy is used.
Supported Engines
| Engine | Value |
|---|
| PostgreSQL | postgres |
| MySQL | mysql |
Do not use aurora-postgresql or aurora-mysql — those are Aurora engines and incompatible with Multi-AZ DB cluster storage settings.
Working Example
The following is taken directly from examples/multi-az/. It provisions a PostgreSQL Multi-AZ RDS cluster with provisioned IOPS storage, Performance Insights, and automatic password rotation.
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-multi-az"
region = "eu-west-1"
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-aurora"
GithubOrg = "terraform-aws-modules"
}
}
module "aurora" {
source = "terraform-aws-modules/rds-aurora/aws"
name = local.name
engine = "postgres" # This uses RDS engine, not Aurora
engine_version = "17.5"
master_username = "root"
vpc_id = module.vpc.vpc_id
db_subnet_group_name = module.vpc.database_subnet_group_name
manage_master_user_password_rotation = true
master_user_password_rotation_automatically_after_days = 30
enabled_cloudwatch_logs_exports = ["postgresql"]
cluster_performance_insights_enabled = true
cluster_performance_insights_retention_period = 31
# Multi-AZ
availability_zones = module.vpc.azs
allocated_storage = 256
cluster_instance_class = "db.c6gd.large"
iops = 2500
storage_type = "io1"
cluster_ca_cert_identifier = "rds-ca-rsa4096-g1"
skip_final_snapshot = true
tags = local.tags
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 6.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
Key Configuration Details
Storage
Multi-AZ RDS clusters require explicit storage configuration. The example uses provisioned IOPS (io1) for predictable performance:
allocated_storage = 256 # GiB per instance
storage_type = "io1" # Required for Multi-AZ
iops = 2500 # Provisioned IOPS
io1 is the required storage_type for Multi-AZ DB clusters. Aurora clusters use aurora or aurora-iopt1 instead.
Instance Class
Multi-AZ DB clusters use different instance families than Aurora. In the example, db.c6gd.large is used — this class has local NVMe SSD storage and is optimized for I/O-intensive workloads:
cluster_instance_class = "db.c6gd.large"
Note that cluster_instance_class here maps to db_cluster_instance_class on the aws_rds_cluster resource (not to individual aws_rds_cluster_instance resources, which are not created for Multi-AZ RDS clusters).
Availability Zones
Pass all three AZs explicitly so the cluster places instances predictably:
availability_zones = module.vpc.azs
If fewer than 3 AZs are specified, RDS will auto-assign them — but this can cause a diff on subsequent Terraform plans.
CA Certificate
The cluster_ca_cert_identifier variable specifies which Certificate Authority the cluster’s TLS certificate should be signed by:
cluster_ca_cert_identifier = "rds-ca-rsa4096-g1"
This is currently only supported for Multi-AZ DB clusters (not Aurora). Choose a CA that matches your client TLS requirements and certificate rotation schedule.
Variable Reference
| Variable | Type | Default | Description |
|---|
engine | string | null | Use mysql or postgres (not Aurora variants) |
allocated_storage | number | null | Storage in GiB per instance — required to enable Multi-AZ mode |
cluster_instance_class | string | null | Instance class for Multi-AZ DB instances (e.g. db.c6gd.large) |
storage_type | string | null | Use io1 for Multi-AZ clusters |
iops | number | null | Provisioned IOPS for io1 storage |
availability_zones | list(string) | null | List of 3 AZs to place instances in |
cluster_ca_cert_identifier | string | null | CA certificate identifier (Multi-AZ only) |