Infrastructure as code for relational databases requires precise control over cluster topology, engine selection, and cross-region resilience. Terraform provides that control for Amazon RDS through the AWS provider and community modules that abstract repetitive cluster patterns. The core constructs are aws_rds_cluster for Aurora clusters with shared storage and aws_db_instance for single-instance databases, with modules adding opinionated defaults for networking, secrets management, and scaling.
Overview of RDS Cluster Management with Terraform
Terraform integrates with RDS by using the AWS provider to define infrastructure as code. You can declare awsdbinstance or awsrdscluster resources in Terraform to create and manage RDS instances or clusters. Terraform plans changes, applies them consistently, and tracks the state of your RDS configurations, making infrastructure deployment repeatable and auditable. Using Terraform with RDS ensures environment consistency, improves version control of database configurations, and enables automation in CI/CD pipelines.
RDS supports engines like MySQL, PostgreSQL, MariaDB, Oracle, and SQL Server and handles routine tasks such as backups, patching, and high availability. When working with Aurora, a cluster provides a shared storage layer and separate awsrdsclusterinstance resources for each node. awsdbinstance provisions a single RDS database, while awsrdscluster creates an Aurora cluster with a shared storage layer and separate awsrdsclusterinstance resources for each node.
Cloud Posse RDS Cluster Module Deep Dive
Terraform module to provision an RDS Aurora cluster for MySQL or Postgres. Supports Amazon Aurora Serverless. For a complete example, see examples/complete.
The module accepts a set of inputs that map directly to RDS cluster behavior and networking. A selection of module parameters includes:
- copytagsto_snapshot | Copy tags to backup snapshots | bool | false | no
- databaseinsightsmode | The database insights mode for the RDS cluster. Valid values are standard, advanced | string | null | no
- dbclusterinstance_class | This setting is required to create a provisioned Multi-AZ DB cluster | string | null | no
- db_name | Database name, default is not to create a database | string | "" | no
- dbparametergroupname | The name to give to the created awsdbparametergroup resource. If omitted, the module will generate a name | string | "" | no
- db_port | Database port | number | 3306 | no
- deletion_protection | If the DB instance should have deletion protection enabled | bool | false | no
- delimiter | Delimiter to be used between ID elements. Defaults to - hyphen. Set to "" to use no delimiter at all | string | null | no
- descriptor_formats | Describe additional descriptors to be output in the descriptors output map. Map of maps
These parameters allow fine-grained control over tagging, insights, instance class, database naming, and naming conventions.
Module Configuration Examples for Aurora PostgreSQL and MySQL Serverless
A typical provisioned Aurora PostgreSQL configuration uses the cloudposse module with explicit engine and sizing:
hcl
module "rds_cluster_aurora_postgres" {
source = "cloudposse/rds-cluster/aws"
name = "postgres"
engine = "aurora-postgresql"
cluster_family = "aurora-postgresql9.6"
cluster_size = 2
namespace = "eg"
stage = "dev"
admin_user = "admin1"
admin_password = "Test123456789"
db_name = "dbname"
db_port = 5432
instance_type = "db.r4.large"
vpc_id = "vpc-xxxxxxxx"
security_groups = ["sg-xxxxxxxx"]
subnets = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
zone_id = "Zxxxxxxxx"
}
Cluster size controls the number of instances. 1 writer, 1 reader corresponds to clustersize = 2. 1 writer, 3 reader corresponds to clustersize = 4. 1 writer, 5 reader corresponds to cluster_size = 6.
For Aurora MySQL Serverless, the module switches to serverless mode and adds scaling configuration:
hcl
module "rds_cluster_aurora_mysql_serverless" {
source = "cloudposse/rds-cluster/aws"
namespace = "eg"
stage = "dev"
name = "db"
engine = "aurora"
engine_mode = "serverless"
cluster_family = "aurora5.6"
cluster_size = 0
admin_user = "admin1"
admin_password = "Test123456789"
db_name = "dbname"
db_port = 3306
instance_type = "db.t2.small"
vpc_id = "vpc-xxxxxxxx"
security_groups = ["sg-xxxxxxxx"]
subnets = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
zone_id = "Zxxxxxxxx"
enable_http_endpoint = true
scaling_configuration = [
{
auto_pause = true
max_capacity = 256
min_capacity =
}
]
}
Cloud Posse recommends pinning every module to a specific version.
Multi-Region Active Active Failover Architecture
In this article, we will go through how to deploy a multi-region AWS RDS cluster with an automatic failover setup using Terraform. By leveraging AWS RDS and Terraform, we can set up highly available, fault-tolerant database architectures across multiple regions. This ensures that your applications remain online even in the event of regional outages, providing resilience and scalability for critical applications.
Before starting, ensure you have the following:
- AWS Account: An active AWS account with the necessary permissions
- AWS CLI: AWS CLI should be configured with your AWS credentials
- Terraform Installed: Terraform must be installed on your local machine
The provider file tells Terraform which provider you are using.
hcl
provider "aws" {
region = local.region_0
profile = "<profile-name>"
default_tags {
tags = {
Owner = "primary"
Project = "AWS Multi Region rds with active/active setup"
Provisioner = "Terraform"
}
}
}
provider "aws" {
alias = "secondory"
region = local.region_1
profile = "<profile-name>"
default_tags {
tags = {
Owner = "secondory"
Project = "AWS Multi Region rds with active/active setup"
Provisioner = "Terraform"
}
}
}
Terraform data sources allow you to fetch information from your cloud provider and use it within your configuration.
Core AWS Provider Integration and Data Sources
Terraform management made easy with orchestration of Terraform workflows end to end, including state management, policy as code, drift detection, resource visualization, context sharing, programmatic configuration, and support for complex, multi-step workflows.
OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.
Basic RDS Instance Definition and Attribute Breakdown
Creating an RDS database instance in AWS using Terraform is quite easy. The awsdbinstance resource block requires a few parameters that define the essential characteristics of the database to be provisioned.
hcl
resource "aws_db_instance" "default" {
allocated_storage = 10
engine = "mysql"
instance_class = "db.t3.micro"
username = "foo"
password = "foobarbaz"
skip_final_snapshot = true
}
Let's examine the attributes:
- allocated_storage: Memory allocated in GB for this database instance
- engine: Choice of database engine. We have selected MySQL as the desired database engine. We can also select Postgres, MariaDB, Oracle, etc
Step 1. Configure a basic RDS instance. The attributes above define storage, engine, instance class, credentials, and final snapshot behavior.
Security Best Practices for Credentials and Secrets Manager
How do I store RDS passwords securely in Terraform? Store passwords in AWS Secrets Manager or SSM Parameter Store and reference them with a data source, or use the managemasteruser_password argument to let RDS handle rotation automatically. Avoid hardcoding credentials in .tf files or state.
Can Terraform manage RDS read replicas? Yes. Set the replicatesourcedb argument on a second awsdbinstance resource, pointing it to the primary instance’s identifier.
A Terraform module for managing a simple Aurora Postgres cluster gets a list of inputs, and creates an Aurora Postgres Cluster, with a configurable number of instances. In addition, it creates a secret on AWS Secrets Manager, to store credentials to access the recently created cluster. This output secret has the root user, password, endpoint and readerendpoint, that represents the read-only endpoint for the Aurora cluster, automatically load-balanced across replicas. You can see more information on awsrds_cluster documentation.
There is a naming convention for the created resources, and the caller is allowed to provide some prefixes and suffixes, that are used to build the names.
Module Variations and Naming Conventions
Hello there! In this post I am going to show you Terraform code example of how to create AWS RDS cluster and mange DB passwords in AWS Secrets Manager.
Ok, let's get started with creating RDS cluster. In my example I am going to create Aurora PostgreSQL Serverless DB. To create a cluster I am going to use existing terraform module. I will put details after each part of the code.
The module approach separates cluster creation from instance provisioning, centralizes secret creation, and provides reader endpoint abstraction. The naming convention allows prefixes and suffixes to be supplied by the caller to build resource names consistently across environments.
Comparison of resource types:
- awsdbinstance: single RDS database instance, standalone storage
- awsrdscluster: Aurora cluster with shared storage, requires awsrdscluster_instance resources for nodes
- Module wrappers: add secrets management, naming conventions, parameter groups, and default tagging
Conclusion
Terraform RDS cluster work spans from basic awsdbinstance definitions to multi-region Aurora failover architectures and module-driven production patterns. Provisioned Aurora PostgreSQL clusters use explicit engine families, cluster size, instance type, and VPC networking inputs. Aurora MySQL Serverless shifts to enginemode serverless with scalingconfiguration for autopause and capacity bounds. Multi-region active active setups require multiple aliased AWS providers with distinct regions and default tags, plus data sources for cross-region referencing. Security best practices favor Secrets Manager or SSM Parameter Store integration and the managemasteruserpassword argument over hardcoded credentials. Module-based approaches provide configurable instance counts, automatic secret creation with endpoint and reader_endpoint outputs, and consistent naming conventions. Together these patterns enable repeatable, auditable, and highly available RDS deployments across single and multi-region topologies.
Sources
- github.com/cloudposse/terraform-aws-rds-cluster
- dev.to/aws-builders/terraform-deploying-multi-region-aws-rds-cluster-with-failover-setup-using-terraform-4ahg
- spacelift.io/blog/terraform-aws-rds
- github.com/madelabs/terraform-aws-rds-cluster
- dev.to/aws-builders/create-rds-cluster-and-manage-passwords-in-2024-4n3d