The aws:rds/cluster:Cluster resource, part of the Pulumi AWS provider, defines RDS Aurora clusters or Multi-AZ DB clusters: their engine selection, availability zones, backup configuration, and scaling behavior. This guide focuses on four capabilities: Aurora MySQL and PostgreSQL cluster creation, Multi-AZ cluster provisioning with storage configuration, Serverless v2 auto-scaling, and Secrets Manager password management.
Clusters typically reference VPC subnets, security groups, and KMS keys, though most examples use default VPC settings. Cluster instances must be added separately using aws.rds.ClusterInstance for non-serverless deployments. The examples are intentionally small. Combine them with your own networking, encryption, and monitoring configuration.
Create an Aurora MySQL cluster with backups
Most Aurora deployments start with a basic cluster configuration that specifies the engine, availability zones, and backup settings.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const _default = new aws.rds.Cluster("default", {
clusterIdentifier: "aurora-cluster-demo",
engine: aws.rds.EngineType.AuroraMysql,
engineVersion: "5.7.mysql_aurora.2.03.2",
availabilityZones: [
"us-west-2a",
"us-west-2b",
"us-west-2c",
],
databaseName: "mydb",
masterUsername: "foo",
masterPassword: "must_be_eight_characters",
backupRetentionPeriod: 5,
preferredBackupWindow: "07:00-09:00",
});
import pulumi
import pulumi_aws as aws
default = aws.rds.Cluster("default",
cluster_identifier="aurora-cluster-demo",
engine=aws.rds.EngineType.AURORA_MYSQL,
engine_version="5.7.mysql_aurora.2.03.2",
availability_zones=[
"us-west-2a",
"us-west-2b",
"us-west-2c",
],
database_name="mydb",
master_username="foo",
master_password="must_be_eight_characters",
backup_retention_period=5,
preferred_backup_window="07:00-09:00")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/rds"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := rds.NewCluster(ctx, "default", &rds.ClusterArgs{
ClusterIdentifier: pulumi.String("aurora-cluster-demo"),
Engine: pulumi.String(rds.EngineTypeAuroraMysql),
EngineVersion: pulumi.String("5.7.mysql_aurora.2.03.2"),
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-west-2a"),
pulumi.String("us-west-2b"),
pulumi.String("us-west-2c"),
},
DatabaseName: pulumi.String("mydb"),
MasterUsername: pulumi.String("foo"),
MasterPassword: pulumi.String("must_be_eight_characters"),
BackupRetentionPeriod: pulumi.Int(5),
PreferredBackupWindow: pulumi.String("07:00-09:00"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var @default = new Aws.Rds.Cluster("default", new()
{
ClusterIdentifier = "aurora-cluster-demo",
Engine = Aws.Rds.EngineType.AuroraMysql,
EngineVersion = "5.7.mysql_aurora.2.03.2",
AvailabilityZones = new[]
{
"us-west-2a",
"us-west-2b",
"us-west-2c",
},
DatabaseName = "mydb",
MasterUsername = "foo",
MasterPassword = "must_be_eight_characters",
BackupRetentionPeriod = 5,
PreferredBackupWindow = "07:00-09:00",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var default_ = new Cluster("default", ClusterArgs.builder()
.clusterIdentifier("aurora-cluster-demo")
.engine("aurora-mysql")
.engineVersion("5.7.mysql_aurora.2.03.2")
.availabilityZones(
"us-west-2a",
"us-west-2b",
"us-west-2c")
.databaseName("mydb")
.masterUsername("foo")
.masterPassword("must_be_eight_characters")
.backupRetentionPeriod(5)
.preferredBackupWindow("07:00-09:00")
.build());
}
}
resources:
default:
type: aws:rds:Cluster
properties:
clusterIdentifier: aurora-cluster-demo
engine: aurora-mysql
engineVersion: 5.7.mysql_aurora.2.03.2
availabilityZones:
- us-west-2a
- us-west-2b
- us-west-2c
databaseName: mydb
masterUsername: foo
masterPassword: must_be_eight_characters
backupRetentionPeriod: 5
preferredBackupWindow: 07:00-09:00
The engine and engineVersion properties select Aurora MySQL 2.x (MySQL 5.7 compatible). The availabilityZones array distributes cluster storage across three zones for high availability. The backupRetentionPeriod and preferredBackupWindow properties configure automated backups to run daily during a maintenance window, retaining snapshots for 5 days.
Create an Aurora PostgreSQL cluster
Teams running PostgreSQL workloads use Aurora PostgreSQL for managed replication and automatic failover while maintaining PostgreSQL compatibility.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const postgresql = new aws.rds.Cluster("postgresql", {
clusterIdentifier: "aurora-cluster-demo",
engine: aws.rds.EngineType.AuroraPostgresql,
availabilityZones: [
"us-west-2a",
"us-west-2b",
"us-west-2c",
],
databaseName: "mydb",
masterUsername: "foo",
masterPassword: "must_be_eight_characters",
backupRetentionPeriod: 5,
preferredBackupWindow: "07:00-09:00",
});
import pulumi
import pulumi_aws as aws
postgresql = aws.rds.Cluster("postgresql",
cluster_identifier="aurora-cluster-demo",
engine=aws.rds.EngineType.AURORA_POSTGRESQL,
availability_zones=[
"us-west-2a",
"us-west-2b",
"us-west-2c",
],
database_name="mydb",
master_username="foo",
master_password="must_be_eight_characters",
backup_retention_period=5,
preferred_backup_window="07:00-09:00")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/rds"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := rds.NewCluster(ctx, "postgresql", &rds.ClusterArgs{
ClusterIdentifier: pulumi.String("aurora-cluster-demo"),
Engine: pulumi.String(rds.EngineTypeAuroraPostgresql),
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-west-2a"),
pulumi.String("us-west-2b"),
pulumi.String("us-west-2c"),
},
DatabaseName: pulumi.String("mydb"),
MasterUsername: pulumi.String("foo"),
MasterPassword: pulumi.String("must_be_eight_characters"),
BackupRetentionPeriod: pulumi.Int(5),
PreferredBackupWindow: pulumi.String("07:00-09:00"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var postgresql = new Aws.Rds.Cluster("postgresql", new()
{
ClusterIdentifier = "aurora-cluster-demo",
Engine = Aws.Rds.EngineType.AuroraPostgresql,
AvailabilityZones = new[]
{
"us-west-2a",
"us-west-2b",
"us-west-2c",
},
DatabaseName = "mydb",
MasterUsername = "foo",
MasterPassword = "must_be_eight_characters",
BackupRetentionPeriod = 5,
PreferredBackupWindow = "07:00-09:00",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var postgresql = new Cluster("postgresql", ClusterArgs.builder()
.clusterIdentifier("aurora-cluster-demo")
.engine("aurora-postgresql")
.availabilityZones(
"us-west-2a",
"us-west-2b",
"us-west-2c")
.databaseName("mydb")
.masterUsername("foo")
.masterPassword("must_be_eight_characters")
.backupRetentionPeriod(5)
.preferredBackupWindow("07:00-09:00")
.build());
}
}
resources:
postgresql:
type: aws:rds:Cluster
properties:
clusterIdentifier: aurora-cluster-demo
engine: aurora-postgresql
availabilityZones:
- us-west-2a
- us-west-2b
- us-west-2c
databaseName: mydb
masterUsername: foo
masterPassword: must_be_eight_characters
backupRetentionPeriod: 5
preferredBackupWindow: 07:00-09:00
Setting engine to EngineType.AuroraPostgresql provisions an Aurora cluster with PostgreSQL compatibility. The cluster inherits the same availability zone distribution and backup configuration patterns as Aurora MySQL.
Create a Multi-AZ RDS cluster with provisioned IOPS
Multi-AZ RDS clusters provide high availability for MySQL and PostgreSQL with synchronous replication across availability zones. Unlike Aurora, these require explicit storage and compute configuration.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.rds.Cluster("example", {
clusterIdentifier: "example",
availabilityZones: [
"us-west-2a",
"us-west-2b",
"us-west-2c",
],
engine: aws.rds.EngineType.Mysql,
dbClusterInstanceClass: "db.r6gd.xlarge",
storageType: "io1",
allocatedStorage: 100,
iops: 1000,
masterUsername: "test",
masterPassword: "mustbeeightcharaters",
});
import pulumi
import pulumi_aws as aws
example = aws.rds.Cluster("example",
cluster_identifier="example",
availability_zones=[
"us-west-2a",
"us-west-2b",
"us-west-2c",
],
engine=aws.rds.EngineType.MYSQL,
db_cluster_instance_class="db.r6gd.xlarge",
storage_type="io1",
allocated_storage=100,
iops=1000,
master_username="test",
master_password="mustbeeightcharaters")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/rds"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := rds.NewCluster(ctx, "example", &rds.ClusterArgs{
ClusterIdentifier: pulumi.String("example"),
AvailabilityZones: pulumi.StringArray{
pulumi.String("us-west-2a"),
pulumi.String("us-west-2b"),
pulumi.String("us-west-2c"),
},
Engine: pulumi.String(rds.EngineTypeMysql),
DbClusterInstanceClass: pulumi.String("db.r6gd.xlarge"),
StorageType: pulumi.String("io1"),
AllocatedStorage: pulumi.Int(100),
Iops: pulumi.Int(1000),
MasterUsername: pulumi.String("test"),
MasterPassword: pulumi.String("mustbeeightcharaters"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Rds.Cluster("example", new()
{
ClusterIdentifier = "example",
AvailabilityZones = new[]
{
"us-west-2a",
"us-west-2b",
"us-west-2c",
},
Engine = Aws.Rds.EngineType.Mysql,
DbClusterInstanceClass = "db.r6gd.xlarge",
StorageType = "io1",
AllocatedStorage = 100,
Iops = 1000,
MasterUsername = "test",
MasterPassword = "mustbeeightcharaters",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Cluster("example", ClusterArgs.builder()
.clusterIdentifier("example")
.availabilityZones(
"us-west-2a",
"us-west-2b",
"us-west-2c")
.engine("mysql")
.dbClusterInstanceClass("db.r6gd.xlarge")
.storageType("io1")
.allocatedStorage(100)
.iops(1000)
.masterUsername("test")
.masterPassword("mustbeeightcharaters")
.build());
}
}
resources:
example:
type: aws:rds:Cluster
properties:
clusterIdentifier: example
availabilityZones:
- us-west-2a
- us-west-2b
- us-west-2c
engine: mysql
dbClusterInstanceClass: db.r6gd.xlarge
storageType: io1
allocatedStorage: 100
iops: 1000
masterUsername: test
masterPassword: mustbeeightcharaters
The dbClusterInstanceClass property specifies the compute capacity for each instance in the cluster. The storageType, allocatedStorage, and iops properties configure provisioned IOPS storage. Multi-AZ clusters require all four properties; Aurora clusters manage storage automatically.
Configure Aurora Serverless v2 with auto-scaling
Serverless v2 clusters automatically scale compute capacity based on workload, eliminating the need to provision fixed instance sizes.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.rds.Cluster("example", {
clusterIdentifier: "example",
engine: aws.rds.EngineType.AuroraPostgresql,
engineMode: aws.rds.EngineMode.Provisioned,
engineVersion: "13.6",
databaseName: "test",
masterUsername: "test",
masterPassword: "must_be_eight_characters",
storageEncrypted: true,
serverlessv2ScalingConfiguration: {
maxCapacity: 1,
minCapacity: 0,
secondsUntilAutoPause: 3600,
},
});
const exampleClusterInstance = new aws.rds.ClusterInstance("example", {
clusterIdentifier: example.id,
instanceClass: "db.serverless",
engine: example.engine.apply((x) => aws.rds.EngineType[x]),
engineVersion: example.engineVersion,
});
import pulumi
import pulumi_aws as aws
example = aws.rds.Cluster("example",
cluster_identifier="example",
engine=aws.rds.EngineType.AURORA_POSTGRESQL,
engine_mode=aws.rds.EngineMode.PROVISIONED,
engine_version="13.6",
database_name="test",
master_username="test",
master_password="must_be_eight_characters",
storage_encrypted=True,
serverlessv2_scaling_configuration={
"max_capacity": 1,
"min_capacity": 0,
"seconds_until_auto_pause": 3600,
})
example_cluster_instance = aws.rds.ClusterInstance("example",
cluster_identifier=example.id,
instance_class="db.serverless",
engine=example.engine.apply(lambda x: aws.rds.EngineType(x)),
engine_version=example.engine_version)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/rds"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := rds.NewCluster(ctx, "example", &rds.ClusterArgs{
ClusterIdentifier: pulumi.String("example"),
Engine: pulumi.String(rds.EngineTypeAuroraPostgresql),
EngineMode: pulumi.String(rds.EngineModeProvisioned),
EngineVersion: pulumi.String("13.6"),
DatabaseName: pulumi.String("test"),
MasterUsername: pulumi.String("test"),
MasterPassword: pulumi.String("must_be_eight_characters"),
StorageEncrypted: pulumi.Bool(true),
Serverlessv2ScalingConfiguration: &rds.ClusterServerlessv2ScalingConfigurationArgs{
MaxCapacity: pulumi.Float64(1),
MinCapacity: pulumi.Float64(0),
SecondsUntilAutoPause: pulumi.Int(3600),
},
})
if err != nil {
return err
}
_, err = rds.NewClusterInstance(ctx, "example", &rds.ClusterInstanceArgs{
ClusterIdentifier: example.ID(),
InstanceClass: pulumi.String("db.serverless"),
Engine: example.Engine.ApplyT(func(x *string) rds.EngineType { return rds.EngineType(*x) }).(rds.EngineTypeOutput),
EngineVersion: example.EngineVersion,
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Rds.Cluster("example", new()
{
ClusterIdentifier = "example",
Engine = Aws.Rds.EngineType.AuroraPostgresql,
EngineMode = Aws.Rds.EngineMode.Provisioned,
EngineVersion = "13.6",
DatabaseName = "test",
MasterUsername = "test",
MasterPassword = "must_be_eight_characters",
StorageEncrypted = true,
Serverlessv2ScalingConfiguration = new Aws.Rds.Inputs.ClusterServerlessv2ScalingConfigurationArgs
{
MaxCapacity = 1,
MinCapacity = 0,
SecondsUntilAutoPause = 3600,
},
});
var exampleClusterInstance = new Aws.Rds.ClusterInstance("example", new()
{
ClusterIdentifier = example.Id,
InstanceClass = "db.serverless",
Engine = example.Engine.Apply(System.Enum.Parse<Aws.Rds.EngineType>),
EngineVersion = example.EngineVersion,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import com.pulumi.aws.rds.inputs.ClusterServerlessv2ScalingConfigurationArgs;
import com.pulumi.aws.rds.ClusterInstance;
import com.pulumi.aws.rds.ClusterInstanceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Cluster("example", ClusterArgs.builder()
.clusterIdentifier("example")
.engine("aurora-postgresql")
.engineMode("provisioned")
.engineVersion("13.6")
.databaseName("test")
.masterUsername("test")
.masterPassword("must_be_eight_characters")
.storageEncrypted(true)
.serverlessv2ScalingConfiguration(ClusterServerlessv2ScalingConfigurationArgs.builder()
.maxCapacity(1.0)
.minCapacity(0.0)
.secondsUntilAutoPause(3600)
.build())
.build());
var exampleClusterInstance = new ClusterInstance("exampleClusterInstance", ClusterInstanceArgs.builder()
.clusterIdentifier(example.id())
.instanceClass("db.serverless")
.engine(example.engine())
.engineVersion(example.engineVersion())
.build());
}
}
resources:
example:
type: aws:rds:Cluster
properties:
clusterIdentifier: example
engine: aurora-postgresql
engineMode: provisioned
engineVersion: '13.6'
databaseName: test
masterUsername: test
masterPassword: must_be_eight_characters
storageEncrypted: true
serverlessv2ScalingConfiguration:
maxCapacity: 1
minCapacity: 0
secondsUntilAutoPause: 3600
exampleClusterInstance:
type: aws:rds:ClusterInstance
name: example
properties:
clusterIdentifier: ${example.id}
instanceClass: db.serverless
engine: ${example.engine}
engineVersion: ${example.engineVersion}
The engineMode must be set to provisioned (not serverless) for Serverless v2. The serverlessv2ScalingConfiguration block defines capacity boundaries: minCapacity and maxCapacity control the scaling range in Aurora Capacity Units (ACUs). Unlike Serverless v1, you must add a ClusterInstance resource with instanceClass set to “db.serverless”. Note that storageEncrypted defaults to false for provisioned engine mode.
Manage master password with Secrets Manager
Storing database passwords in Secrets Manager removes them from Pulumi state and enables automatic rotation.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.rds.Cluster("test", {
clusterIdentifier: "example",
databaseName: "test",
manageMasterUserPassword: true,
masterUsername: "test",
});
import pulumi
import pulumi_aws as aws
test = aws.rds.Cluster("test",
cluster_identifier="example",
database_name="test",
manage_master_user_password=True,
master_username="test")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/rds"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := rds.NewCluster(ctx, "test", &rds.ClusterArgs{
ClusterIdentifier: pulumi.String("example"),
DatabaseName: pulumi.String("test"),
ManageMasterUserPassword: pulumi.Bool(true),
MasterUsername: pulumi.String("test"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = new Aws.Rds.Cluster("test", new()
{
ClusterIdentifier = "example",
DatabaseName = "test",
ManageMasterUserPassword = true,
MasterUsername = "test",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var test = new Cluster("test", ClusterArgs.builder()
.clusterIdentifier("example")
.databaseName("test")
.manageMasterUserPassword(true)
.masterUsername("test")
.build());
}
}
resources:
test:
type: aws:rds:Cluster
properties:
clusterIdentifier: example
databaseName: test
manageMasterUserPassword: true
masterUsername: test
Setting manageMasterUserPassword to true instructs RDS to create and manage a secret in Secrets Manager. You must omit the masterPassword property when using this feature. RDS handles secret rotation and updates automatically.
Restore a global cluster from snapshot
Global clusters span multiple regions for disaster recovery and low-latency reads. When restoring from a snapshot, you must create the cluster first, then attach it to the global cluster.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = aws.rds.getClusterSnapshot({
dbClusterIdentifier: "example-original-cluster",
mostRecent: true,
});
const exampleCluster = new aws.rds.Cluster("example", {
engine: aws.rds.EngineType.Aurora,
engineVersion: "5.6.mysql_aurora.1.22.4",
clusterIdentifier: "example",
snapshotIdentifier: example.then(example => example.id),
});
const exampleGlobalCluster = new aws.rds.GlobalCluster("example", {
globalClusterIdentifier: "example",
sourceDbClusterIdentifier: exampleCluster.arn,
forceDestroy: true,
});
import pulumi
import pulumi_aws as aws
example = aws.rds.get_cluster_snapshot(db_cluster_identifier="example-original-cluster",
most_recent=True)
example_cluster = aws.rds.Cluster("example",
engine=aws.rds.EngineType.AURORA,
engine_version="5.6.mysql_aurora.1.22.4",
cluster_identifier="example",
snapshot_identifier=example.id)
example_global_cluster = aws.rds.GlobalCluster("example",
global_cluster_identifier="example",
source_db_cluster_identifier=example_cluster.arn,
force_destroy=True)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/rds"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := rds.LookupClusterSnapshot(ctx, &rds.LookupClusterSnapshotArgs{
DbClusterIdentifier: pulumi.StringRef("example-original-cluster"),
MostRecent: pulumi.BoolRef(true),
}, nil)
if err != nil {
return err
}
exampleCluster, err := rds.NewCluster(ctx, "example", &rds.ClusterArgs{
Engine: pulumi.String(rds.EngineTypeAurora),
EngineVersion: pulumi.String("5.6.mysql_aurora.1.22.4"),
ClusterIdentifier: pulumi.String("example"),
SnapshotIdentifier: pulumi.String(example.Id),
})
if err != nil {
return err
}
_, err = rds.NewGlobalCluster(ctx, "example", &rds.GlobalClusterArgs{
GlobalClusterIdentifier: pulumi.String("example"),
SourceDbClusterIdentifier: exampleCluster.Arn,
ForceDestroy: pulumi.Bool(true),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = Aws.Rds.GetClusterSnapshot.Invoke(new()
{
DbClusterIdentifier = "example-original-cluster",
MostRecent = true,
});
var exampleCluster = new Aws.Rds.Cluster("example", new()
{
Engine = Aws.Rds.EngineType.Aurora,
EngineVersion = "5.6.mysql_aurora.1.22.4",
ClusterIdentifier = "example",
SnapshotIdentifier = example.Apply(getClusterSnapshotResult => getClusterSnapshotResult.Id),
});
var exampleGlobalCluster = new Aws.Rds.GlobalCluster("example", new()
{
GlobalClusterIdentifier = "example",
SourceDbClusterIdentifier = exampleCluster.Arn,
ForceDestroy = true,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.RdsFunctions;
import com.pulumi.aws.rds.inputs.GetClusterSnapshotArgs;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import com.pulumi.aws.rds.GlobalCluster;
import com.pulumi.aws.rds.GlobalClusterArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var example = RdsFunctions.getClusterSnapshot(GetClusterSnapshotArgs.builder()
.dbClusterIdentifier("example-original-cluster")
.mostRecent(true)
.build());
var exampleCluster = new Cluster("exampleCluster", ClusterArgs.builder()
.engine("aurora")
.engineVersion("5.6.mysql_aurora.1.22.4")
.clusterIdentifier("example")
.snapshotIdentifier(example.id())
.build());
var exampleGlobalCluster = new GlobalCluster("exampleGlobalCluster", GlobalClusterArgs.builder()
.globalClusterIdentifier("example")
.sourceDbClusterIdentifier(exampleCluster.arn())
.forceDestroy(true)
.build());
}
}
resources:
exampleCluster:
type: aws:rds:Cluster
name: example
properties:
engine: aurora
engineVersion: 5.6.mysql_aurora.1.22.4
clusterIdentifier: example
snapshotIdentifier: ${example.id}
exampleGlobalCluster:
type: aws:rds:GlobalCluster
name: example
properties:
globalClusterIdentifier: example
sourceDbClusterIdentifier: ${exampleCluster.arn}
forceDestroy: true
variables:
example:
fn::invoke:
function: aws:rds:getClusterSnapshot
arguments:
dbClusterIdentifier: example-original-cluster
mostRecent: true
The getClusterSnapshot function retrieves the most recent snapshot from an existing cluster. The snapshotIdentifier property restores the cluster from that snapshot. The GlobalCluster resource then references the restored cluster’s ARN via sourceDbClusterIdentifier. This two-step process is required; you cannot restore from snapshot and join a global cluster in a single operation.
Beyond these examples
These snippets focus on specific cluster-level features: Aurora and Multi-AZ cluster types, Serverless v2 auto-scaling, Secrets Manager password management, and global cluster snapshot restoration. They’re intentionally minimal rather than full database deployments.
The examples may reference pre-existing infrastructure such as VPC, subnets, and security groups (most examples use defaults), KMS keys for encryption (when not using defaults), and snapshots for restoration scenarios. They focus on configuring the cluster rather than provisioning everything around it.
To keep things focused, common cluster patterns are omitted, including:
- Storage encryption and KMS key configuration
- VPC and subnet placement (dbSubnetGroupName)
- Security group associations (vpcSecurityGroupIds)
- IAM database authentication and roles
- Performance Insights and Enhanced Monitoring
- CloudWatch log exports and backup windows
These omissions are intentional: the goal is to illustrate how each cluster feature is wired, not provide drop-in database modules. See the RDS Cluster resource reference for all available configuration options.
Let's create AWS RDS Aurora Clusters
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Cluster Types & Configuration
aurora-mysql, aurora-postgresql) and don’t require db_cluster_instance_class. Multi-AZ DB clusters use standard engines (mysql, postgres) and require engine, storage_type, allocated_storage, iops, and db_cluster_instance_class.engine_mode to provisioned (not serverless), configure serverlessv2_scaling_configuration, and add an aws.rds.ClusterInstance with instance_class set to db.serverless. Note that storage_encrypted defaults to false for Serverless v2, unlike v1.global (Aurora MySQL 1.21 and earlier only), parallelquery, provisioned (default), and serverless. Serverless v2 uses provisioned mode, not serverless.availability_zones, cluster_identifier, database_name, db_subnet_group_name, db_system_id, engine, engine_mode, kms_key_id, master_username, restore_to_point_in_time, snapshot_identifier, source_region, and storage_encrypted. Multi-AZ clusters also cannot change storage_type.Security & Password Management
manage_master_user_password to true to let RDS manage the password in AWS Secrets Manager. You cannot use both manage_master_user_password and master_password together.master_user_secret_kms_key_id with your KMS key ARN, ID, or alias. If not specified, AWS uses your account’s default KMS key.storage_encrypted to true and optionally specify kms_key_id. Note that encryption defaults differ: false for provisioned mode and true for serverless mode. When restoring from an unencrypted snapshot, you must provide kms_key_id to encrypt the restored cluster.High Availability & Disaster Recovery
lifecycle.ignore_changes for the availability_zones property.backup_retention_period to a higher value for longer retention.Maintenance & Updates
apply_immediately to true can result in brief downtime as the server reboots. The default is false, which applies changes during the next maintenance window.engine_version results in an outage. Plan accordingly and consider using apply_immediately to control when the update occurs.master_username does not support in-place updates and cannot be changed during a restore from snapshot.Common Configuration Issues
aws.rds.ClusterRoleAssociation resource and the iam_roles attribute on the cluster. Use one method or the other to avoid conflicts that overwrite associations.db_subnet_group_name on the cluster must match the db_subnet_group_name specified on every aws.rds.ClusterInstance in the cluster.ca_certificate_identifier. Aurora clusters do not support this property.