Create AWS RDS Global Clusters

The aws:rds/globalCluster:GlobalCluster resource, part of the Pulumi AWS provider, defines an Aurora global database that replicates data across multiple AWS regions through high-speed storage-level replication. This guide focuses on three capabilities: creating multi-region MySQL and PostgreSQL global clusters, promoting existing regional clusters to global, and coordinating engine version upgrades.

Global clusters coordinate multiple regional Aurora clusters: one primary cluster handles writes, while secondary clusters in other regions provide read replicas and failover targets. The examples are intentionally small. Combine them with your own VPC configuration, security groups, and monitoring.

Create a MySQL global cluster with primary and secondary regions

Most global deployments start by creating a global cluster container, then attaching primary and secondary regional clusters for disaster recovery and low-latency reads.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.rds.GlobalCluster("example", {
    globalClusterIdentifier: "global-test",
    engine: "aurora",
    engineVersion: "5.6.mysql_aurora.1.22.2",
    databaseName: "example_db",
});
const primary = new aws.rds.Cluster("primary", {
    engine: example.engine,
    engineVersion: example.engineVersion,
    clusterIdentifier: "test-primary-cluster",
    masterUsername: "username",
    masterPassword: "somepass123",
    databaseName: "example_db",
    globalClusterIdentifier: example.id,
    dbSubnetGroupName: "default",
});
const primaryClusterInstance = new aws.rds.ClusterInstance("primary", {
    engine: example.engine.apply((x) => aws.rds.EngineType[x]),
    engineVersion: example.engineVersion,
    identifier: "test-primary-cluster-instance",
    clusterIdentifier: primary.id,
    instanceClass: aws.rds.InstanceType.R4_Large,
    dbSubnetGroupName: "default",
});
const secondary = new aws.rds.Cluster("secondary", {
    engine: example.engine,
    engineVersion: example.engineVersion,
    clusterIdentifier: "test-secondary-cluster",
    globalClusterIdentifier: example.id,
    dbSubnetGroupName: "default",
}, {
    dependsOn: [primaryClusterInstance],
});
const secondaryClusterInstance = new aws.rds.ClusterInstance("secondary", {
    engine: example.engine.apply((x) => aws.rds.EngineType[x]),
    engineVersion: example.engineVersion,
    identifier: "test-secondary-cluster-instance",
    clusterIdentifier: secondary.id,
    instanceClass: aws.rds.InstanceType.R4_Large,
    dbSubnetGroupName: "default",
});
import pulumi
import pulumi_aws as aws

example = aws.rds.GlobalCluster("example",
    global_cluster_identifier="global-test",
    engine="aurora",
    engine_version="5.6.mysql_aurora.1.22.2",
    database_name="example_db")
primary = aws.rds.Cluster("primary",
    engine=example.engine,
    engine_version=example.engine_version,
    cluster_identifier="test-primary-cluster",
    master_username="username",
    master_password="somepass123",
    database_name="example_db",
    global_cluster_identifier=example.id,
    db_subnet_group_name="default")
primary_cluster_instance = aws.rds.ClusterInstance("primary",
    engine=example.engine,
    engine_version=example.engine_version,
    identifier="test-primary-cluster-instance",
    cluster_identifier=primary.id,
    instance_class=aws.rds.InstanceType.R4_LARGE,
    db_subnet_group_name="default")
secondary = aws.rds.Cluster("secondary",
    engine=example.engine,
    engine_version=example.engine_version,
    cluster_identifier="test-secondary-cluster",
    global_cluster_identifier=example.id,
    db_subnet_group_name="default",
    opts = pulumi.ResourceOptions(depends_on=[primary_cluster_instance]))
secondary_cluster_instance = aws.rds.ClusterInstance("secondary",
    engine=example.engine,
    engine_version=example.engine_version,
    identifier="test-secondary-cluster-instance",
    cluster_identifier=secondary.id,
    instance_class=aws.rds.InstanceType.R4_LARGE,
    db_subnet_group_name="default")
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.NewGlobalCluster(ctx, "example", &rds.GlobalClusterArgs{
			GlobalClusterIdentifier: pulumi.String("global-test"),
			Engine:                  pulumi.String("aurora"),
			EngineVersion:           pulumi.String("5.6.mysql_aurora.1.22.2"),
			DatabaseName:            pulumi.String("example_db"),
		})
		if err != nil {
			return err
		}
		primary, err := rds.NewCluster(ctx, "primary", &rds.ClusterArgs{
			Engine:                  example.Engine,
			EngineVersion:           example.EngineVersion,
			ClusterIdentifier:       pulumi.String("test-primary-cluster"),
			MasterUsername:          pulumi.String("username"),
			MasterPassword:          pulumi.String("somepass123"),
			DatabaseName:            pulumi.String("example_db"),
			GlobalClusterIdentifier: example.ID(),
			DbSubnetGroupName:       pulumi.String("default"),
		})
		if err != nil {
			return err
		}
		primaryClusterInstance, err := rds.NewClusterInstance(ctx, "primary", &rds.ClusterInstanceArgs{
			Engine:            example.Engine.ApplyT(func(x *string) rds.EngineType { return rds.EngineType(*x) }).(rds.EngineTypeOutput),
			EngineVersion:     example.EngineVersion,
			Identifier:        pulumi.String("test-primary-cluster-instance"),
			ClusterIdentifier: primary.ID(),
			InstanceClass:     pulumi.String(rds.InstanceType_R4_Large),
			DbSubnetGroupName: pulumi.String("default"),
		})
		if err != nil {
			return err
		}
		secondary, err := rds.NewCluster(ctx, "secondary", &rds.ClusterArgs{
			Engine:                  example.Engine,
			EngineVersion:           example.EngineVersion,
			ClusterIdentifier:       pulumi.String("test-secondary-cluster"),
			GlobalClusterIdentifier: example.ID(),
			DbSubnetGroupName:       pulumi.String("default"),
		}, pulumi.DependsOn([]pulumi.Resource{
			primaryClusterInstance,
		}))
		if err != nil {
			return err
		}
		_, err = rds.NewClusterInstance(ctx, "secondary", &rds.ClusterInstanceArgs{
			Engine:            example.Engine.ApplyT(func(x *string) rds.EngineType { return rds.EngineType(*x) }).(rds.EngineTypeOutput),
			EngineVersion:     example.EngineVersion,
			Identifier:        pulumi.String("test-secondary-cluster-instance"),
			ClusterIdentifier: secondary.ID(),
			InstanceClass:     pulumi.String(rds.InstanceType_R4_Large),
			DbSubnetGroupName: pulumi.String("default"),
		})
		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.GlobalCluster("example", new()
    {
        GlobalClusterIdentifier = "global-test",
        Engine = "aurora",
        EngineVersion = "5.6.mysql_aurora.1.22.2",
        DatabaseName = "example_db",
    });

    var primary = new Aws.Rds.Cluster("primary", new()
    {
        Engine = example.Engine,
        EngineVersion = example.EngineVersion,
        ClusterIdentifier = "test-primary-cluster",
        MasterUsername = "username",
        MasterPassword = "somepass123",
        DatabaseName = "example_db",
        GlobalClusterIdentifier = example.Id,
        DbSubnetGroupName = "default",
    });

    var primaryClusterInstance = new Aws.Rds.ClusterInstance("primary", new()
    {
        Engine = example.Engine.Apply(System.Enum.Parse<Aws.Rds.EngineType>),
        EngineVersion = example.EngineVersion,
        Identifier = "test-primary-cluster-instance",
        ClusterIdentifier = primary.Id,
        InstanceClass = Aws.Rds.InstanceType.R4_Large,
        DbSubnetGroupName = "default",
    });

    var secondary = new Aws.Rds.Cluster("secondary", new()
    {
        Engine = example.Engine,
        EngineVersion = example.EngineVersion,
        ClusterIdentifier = "test-secondary-cluster",
        GlobalClusterIdentifier = example.Id,
        DbSubnetGroupName = "default",
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            primaryClusterInstance,
        },
    });

    var secondaryClusterInstance = new Aws.Rds.ClusterInstance("secondary", new()
    {
        Engine = example.Engine.Apply(System.Enum.Parse<Aws.Rds.EngineType>),
        EngineVersion = example.EngineVersion,
        Identifier = "test-secondary-cluster-instance",
        ClusterIdentifier = secondary.Id,
        InstanceClass = Aws.Rds.InstanceType.R4_Large,
        DbSubnetGroupName = "default",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.GlobalCluster;
import com.pulumi.aws.rds.GlobalClusterArgs;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
import com.pulumi.aws.rds.ClusterInstance;
import com.pulumi.aws.rds.ClusterInstanceArgs;
import com.pulumi.resources.CustomResourceOptions;
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 GlobalCluster("example", GlobalClusterArgs.builder()
            .globalClusterIdentifier("global-test")
            .engine("aurora")
            .engineVersion("5.6.mysql_aurora.1.22.2")
            .databaseName("example_db")
            .build());

        var primary = new Cluster("primary", ClusterArgs.builder()
            .engine(example.engine())
            .engineVersion(example.engineVersion())
            .clusterIdentifier("test-primary-cluster")
            .masterUsername("username")
            .masterPassword("somepass123")
            .databaseName("example_db")
            .globalClusterIdentifier(example.id())
            .dbSubnetGroupName("default")
            .build());

        var primaryClusterInstance = new ClusterInstance("primaryClusterInstance", ClusterInstanceArgs.builder()
            .engine(example.engine())
            .engineVersion(example.engineVersion())
            .identifier("test-primary-cluster-instance")
            .clusterIdentifier(primary.id())
            .instanceClass("db.r4.large")
            .dbSubnetGroupName("default")
            .build());

        var secondary = new Cluster("secondary", ClusterArgs.builder()
            .engine(example.engine())
            .engineVersion(example.engineVersion())
            .clusterIdentifier("test-secondary-cluster")
            .globalClusterIdentifier(example.id())
            .dbSubnetGroupName("default")
            .build(), CustomResourceOptions.builder()
                .dependsOn(primaryClusterInstance)
                .build());

        var secondaryClusterInstance = new ClusterInstance("secondaryClusterInstance", ClusterInstanceArgs.builder()
            .engine(example.engine())
            .engineVersion(example.engineVersion())
            .identifier("test-secondary-cluster-instance")
            .clusterIdentifier(secondary.id())
            .instanceClass("db.r4.large")
            .dbSubnetGroupName("default")
            .build());

    }
}
resources:
  example:
    type: aws:rds:GlobalCluster
    properties:
      globalClusterIdentifier: global-test
      engine: aurora
      engineVersion: 5.6.mysql_aurora.1.22.2
      databaseName: example_db
  primary:
    type: aws:rds:Cluster
    properties:
      engine: ${example.engine}
      engineVersion: ${example.engineVersion}
      clusterIdentifier: test-primary-cluster
      masterUsername: username
      masterPassword: somepass123
      databaseName: example_db
      globalClusterIdentifier: ${example.id}
      dbSubnetGroupName: default
  primaryClusterInstance:
    type: aws:rds:ClusterInstance
    name: primary
    properties:
      engine: ${example.engine}
      engineVersion: ${example.engineVersion}
      identifier: test-primary-cluster-instance
      clusterIdentifier: ${primary.id}
      instanceClass: db.r4.large
      dbSubnetGroupName: default
  secondary:
    type: aws:rds:Cluster
    properties:
      engine: ${example.engine}
      engineVersion: ${example.engineVersion}
      clusterIdentifier: test-secondary-cluster
      globalClusterIdentifier: ${example.id}
      dbSubnetGroupName: default
    options:
      dependsOn:
        - ${primaryClusterInstance}
  secondaryClusterInstance:
    type: aws:rds:ClusterInstance
    name: secondary
    properties:
      engine: ${example.engine}
      engineVersion: ${example.engineVersion}
      identifier: test-secondary-cluster-instance
      clusterIdentifier: ${secondary.id}
      instanceClass: db.r4.large
      dbSubnetGroupName: default

The global cluster defines the engine and version that all member clusters must use. The primary cluster receives writes and replicates to secondaries through Aurora’s storage subsystem. The dependsOn relationship ensures the primary cluster instance exists before creating the secondary cluster, which is required for replication to begin. Each regional cluster needs its own cluster instances to handle queries.

Promote an existing cluster to global

Applications with established regional clusters can convert them to global clusters without recreating the database.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.rds.Cluster("example", {});
const exampleGlobalCluster = new aws.rds.GlobalCluster("example", {
    forceDestroy: true,
    globalClusterIdentifier: "example",
    sourceDbClusterIdentifier: example.arn,
});
import pulumi
import pulumi_aws as aws

example = aws.rds.Cluster("example")
example_global_cluster = aws.rds.GlobalCluster("example",
    force_destroy=True,
    global_cluster_identifier="example",
    source_db_cluster_identifier=example.arn)
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", nil)
		if err != nil {
			return err
		}
		_, err = rds.NewGlobalCluster(ctx, "example", &rds.GlobalClusterArgs{
			ForceDestroy:              pulumi.Bool(true),
			GlobalClusterIdentifier:   pulumi.String("example"),
			SourceDbClusterIdentifier: example.Arn,
		})
		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");

    var exampleGlobalCluster = new Aws.Rds.GlobalCluster("example", new()
    {
        ForceDestroy = true,
        GlobalClusterIdentifier = "example",
        SourceDbClusterIdentifier = example.Arn,
    });

});
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.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) {
        var example = new Cluster("example");

        var exampleGlobalCluster = new GlobalCluster("exampleGlobalCluster", GlobalClusterArgs.builder()
            .forceDestroy(true)
            .globalClusterIdentifier("example")
            .sourceDbClusterIdentifier(example.arn())
            .build());

    }
}
resources:
  example:
    type: aws:rds:Cluster
  exampleGlobalCluster:
    type: aws:rds:GlobalCluster
    name: example
    properties:
      forceDestroy: true
      globalClusterIdentifier: example
      sourceDbClusterIdentifier: ${example.arn}

The sourceDbClusterIdentifier property references an existing Aurora cluster by ARN. The global cluster inherits the engine and engineVersion from the source cluster. The forceDestroy property allows Pulumi to detach member clusters during teardown; without it, you must manually remove clusters before destroying the global cluster.

Upgrade engine versions across all regions

Global clusters require coordinated engine upgrades across all member clusters, which Pulumi handles through the global cluster resource.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.rds.GlobalCluster("example", {
    globalClusterIdentifier: "kyivkharkiv",
    engine: "aurora-mysql",
    engineVersion: "5.7.mysql_aurora.2.07.5",
});
const primary = new aws.rds.Cluster("primary", {
    allowMajorVersionUpgrade: true,
    applyImmediately: true,
    clusterIdentifier: "odessadnipro",
    databaseName: "totoro",
    engine: example.engine,
    engineVersion: example.engineVersion,
    globalClusterIdentifier: example.id,
    masterPassword: "satsukimae",
    masterUsername: "maesatsuki",
    skipFinalSnapshot: true,
});
const primaryClusterInstance = new aws.rds.ClusterInstance("primary", {
    applyImmediately: true,
    clusterIdentifier: primary.id,
    engine: primary.engine.apply((x) => aws.rds.EngineType[x]),
    engineVersion: primary.engineVersion,
    identifier: "donetsklviv",
    instanceClass: aws.rds.InstanceType.R4_Large,
});
import pulumi
import pulumi_aws as aws

example = aws.rds.GlobalCluster("example",
    global_cluster_identifier="kyivkharkiv",
    engine="aurora-mysql",
    engine_version="5.7.mysql_aurora.2.07.5")
primary = aws.rds.Cluster("primary",
    allow_major_version_upgrade=True,
    apply_immediately=True,
    cluster_identifier="odessadnipro",
    database_name="totoro",
    engine=example.engine,
    engine_version=example.engine_version,
    global_cluster_identifier=example.id,
    master_password="satsukimae",
    master_username="maesatsuki",
    skip_final_snapshot=True)
primary_cluster_instance = aws.rds.ClusterInstance("primary",
    apply_immediately=True,
    cluster_identifier=primary.id,
    engine=primary.engine,
    engine_version=primary.engine_version,
    identifier="donetsklviv",
    instance_class=aws.rds.InstanceType.R4_LARGE)
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.NewGlobalCluster(ctx, "example", &rds.GlobalClusterArgs{
			GlobalClusterIdentifier: pulumi.String("kyivkharkiv"),
			Engine:                  pulumi.String("aurora-mysql"),
			EngineVersion:           pulumi.String("5.7.mysql_aurora.2.07.5"),
		})
		if err != nil {
			return err
		}
		primary, err := rds.NewCluster(ctx, "primary", &rds.ClusterArgs{
			AllowMajorVersionUpgrade: pulumi.Bool(true),
			ApplyImmediately:         pulumi.Bool(true),
			ClusterIdentifier:        pulumi.String("odessadnipro"),
			DatabaseName:             pulumi.String("totoro"),
			Engine:                   example.Engine,
			EngineVersion:            example.EngineVersion,
			GlobalClusterIdentifier:  example.ID(),
			MasterPassword:           pulumi.String("satsukimae"),
			MasterUsername:           pulumi.String("maesatsuki"),
			SkipFinalSnapshot:        pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		_, err = rds.NewClusterInstance(ctx, "primary", &rds.ClusterInstanceArgs{
			ApplyImmediately:  pulumi.Bool(true),
			ClusterIdentifier: primary.ID(),
			Engine:            primary.Engine.ApplyT(func(x *string) rds.EngineType { return rds.EngineType(*x) }).(rds.EngineTypeOutput),
			EngineVersion:     primary.EngineVersion,
			Identifier:        pulumi.String("donetsklviv"),
			InstanceClass:     pulumi.String(rds.InstanceType_R4_Large),
		})
		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.GlobalCluster("example", new()
    {
        GlobalClusterIdentifier = "kyivkharkiv",
        Engine = "aurora-mysql",
        EngineVersion = "5.7.mysql_aurora.2.07.5",
    });

    var primary = new Aws.Rds.Cluster("primary", new()
    {
        AllowMajorVersionUpgrade = true,
        ApplyImmediately = true,
        ClusterIdentifier = "odessadnipro",
        DatabaseName = "totoro",
        Engine = example.Engine,
        EngineVersion = example.EngineVersion,
        GlobalClusterIdentifier = example.Id,
        MasterPassword = "satsukimae",
        MasterUsername = "maesatsuki",
        SkipFinalSnapshot = true,
    });

    var primaryClusterInstance = new Aws.Rds.ClusterInstance("primary", new()
    {
        ApplyImmediately = true,
        ClusterIdentifier = primary.Id,
        Engine = primary.Engine.Apply(System.Enum.Parse<Aws.Rds.EngineType>),
        EngineVersion = primary.EngineVersion,
        Identifier = "donetsklviv",
        InstanceClass = Aws.Rds.InstanceType.R4_Large,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.rds.GlobalCluster;
import com.pulumi.aws.rds.GlobalClusterArgs;
import com.pulumi.aws.rds.Cluster;
import com.pulumi.aws.rds.ClusterArgs;
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 GlobalCluster("example", GlobalClusterArgs.builder()
            .globalClusterIdentifier("kyivkharkiv")
            .engine("aurora-mysql")
            .engineVersion("5.7.mysql_aurora.2.07.5")
            .build());

        var primary = new Cluster("primary", ClusterArgs.builder()
            .allowMajorVersionUpgrade(true)
            .applyImmediately(true)
            .clusterIdentifier("odessadnipro")
            .databaseName("totoro")
            .engine(example.engine())
            .engineVersion(example.engineVersion())
            .globalClusterIdentifier(example.id())
            .masterPassword("satsukimae")
            .masterUsername("maesatsuki")
            .skipFinalSnapshot(true)
            .build());

        var primaryClusterInstance = new ClusterInstance("primaryClusterInstance", ClusterInstanceArgs.builder()
            .applyImmediately(true)
            .clusterIdentifier(primary.id())
            .engine(primary.engine())
            .engineVersion(primary.engineVersion())
            .identifier("donetsklviv")
            .instanceClass("db.r4.large")
            .build());

    }
}
resources:
  example:
    type: aws:rds:GlobalCluster
    properties:
      globalClusterIdentifier: kyivkharkiv
      engine: aurora-mysql
      engineVersion: 5.7.mysql_aurora.2.07.5
  primary:
    type: aws:rds:Cluster
    properties:
      allowMajorVersionUpgrade: true
      applyImmediately: true
      clusterIdentifier: odessadnipro
      databaseName: totoro
      engine: ${example.engine}
      engineVersion: ${example.engineVersion}
      globalClusterIdentifier: ${example.id}
      masterPassword: satsukimae
      masterUsername: maesatsuki
      skipFinalSnapshot: true
  primaryClusterInstance:
    type: aws:rds:ClusterInstance
    name: primary
    properties:
      applyImmediately: true
      clusterIdentifier: ${primary.id}
      engine: ${primary.engine}
      engineVersion: ${primary.engineVersion}
      identifier: donetsklviv
      instanceClass: db.r4.large

When you change engineVersion on the global cluster, Pulumi upgrades all member clusters automatically. The allowMajorVersionUpgrade and applyImmediately properties on the regional cluster control upgrade behavior. You must use ignoreChanges for engineVersion on the aws.rds.Cluster resources to avoid “inconsistent final plan” errors, since the global cluster modifies the regional cluster’s engine version outside of the regional cluster’s own configuration.

Beyond these examples

These snippets focus on specific global cluster features: multi-region replication with primary and secondary clusters, promoting existing clusters to global, and coordinated engine version upgrades. They’re intentionally minimal rather than full database deployments.

The examples rely on pre-existing infrastructure such as DB subnet groups in each region, AWS provider configuration for multiple regions, and existing Aurora clusters for the promotion scenario. They focus on configuring the global cluster rather than provisioning the complete networking and security infrastructure.

To keep things focused, common global cluster patterns are omitted, including:

  • Encryption configuration (storageEncrypted, KMS keys)
  • Deletion protection and backup retention
  • Monitoring and performance insights
  • Network isolation and security groups

These omissions are intentional: the goal is to illustrate how each global cluster feature is wired, not provide drop-in database modules. See the RDS Global Cluster resource reference for all available configuration options.

Let's create AWS RDS Global Clusters

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Engine Upgrades & Versioning
Why am I getting 'Provider produced inconsistent final plan' when upgrading my global cluster's engine version?
When you upgrade engineVersion on aws.rds.GlobalCluster, Pulumi attempts to upgrade associated aws.rds.Cluster resources, causing this error. Use ignoreChanges for engineVersion on your aws.rds.Cluster resources to avoid the conflict.
How do I upgrade the engine version of my global cluster?
Update engineVersion on the aws.rds.GlobalCluster resource. The provider will automatically upgrade all cluster members. Add ignoreChanges for engineVersion on associated aws.rds.Cluster resources to prevent plan inconsistencies.
What engine versions are compatible with global clusters?
The engine, engineVersion, and instanceClass (on aws.rds.ClusterInstance) must together support global databases. Valid engines are aurora, aurora-mysql, and aurora-postgresql.
Creating from Existing Clusters
How do I create a global cluster from an existing DB cluster?
Set sourceDbClusterIdentifier to the ARN of your existing cluster and enable forceDestroy. The forceDestroy setting is required to remove cluster members when destroying the global cluster.
What happens when I set both sourceDbClusterIdentifier and engine/engineVersion?
During creation, all engine-related values are ignored and the global cluster inherits engine and engineVersion from the source cluster. After the first apply, any differences between inherited and configured values trigger an in-place update.
Can I upgrade a global cluster created from an existing cluster?
Yes. After initial creation, remove sourceDbClusterIdentifier and replace it with engine and engineVersion. This allows you to upgrade the global cluster’s engine version.
Is encryption enabled by default for global clusters?
No, storageEncrypted defaults to false unless you specify sourceDbClusterIdentifier pointing to an encrypted cluster. Encryption settings are immutable after creation.
Import & Drift Detection
Why does my imported global cluster show perpetual drift for sourceDbClusterIdentifier?
The sourceDbClusterIdentifier argument has no API method for reading after creation, causing Pulumi to always show a difference. Either omit this argument from your program or use ignoreChanges to hide the drift.
Why does forceDestroy show a difference after importing?
The forceDestroy argument only exists within the provider and isn’t stored in AWS. Pulumi will show a difference on the first plan after import to update the state. This change is safe to apply immediately.
Configuration & Immutability
What properties can't be changed after creating a global cluster?
The following properties are immutable: databaseName, engine, globalClusterIdentifier, sourceDbClusterIdentifier, and storageEncrypted. Changing these requires recreating the global cluster.
How do I set up primary and secondary clusters in different regions?
Create the primary cluster and its instance first, then create secondary clusters using dependsOn to reference the primary cluster instance. This ensures proper creation order across regions.
Can I prevent accidental deletion of my global cluster?
Yes, set deletionProtection to true. This prevents the database from being deleted. The default is false.

Using a different cloud?

Explore database guides for other cloud providers: