Deploy GCP AlloyDB Clusters

The gcp:alloydb/cluster:Cluster resource, part of the Pulumi GCP provider, defines an AlloyDB cluster container that establishes network placement, backup policies, and replication topology. This guide focuses on four capabilities: network placement and regional configuration, automated and continuous backup policies, disaster recovery through restore operations, and cross-region replication with secondary clusters.

AlloyDB clusters require VPC networks and VPC peering configuration. The cluster itself is a container; you provision Instance resources separately to run actual database workloads. The examples are intentionally small. Combine them with your own VPC infrastructure and instance configurations.

Create a minimal cluster in a VPC network

Most deployments start by defining the cluster container that establishes network placement and regional location.

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

const defaultNetwork = new gcp.compute.Network("default", {name: "alloydb-cluster"});
const _default = new gcp.alloydb.Cluster("default", {
    clusterId: "alloydb-cluster",
    location: "us-central1",
    networkConfig: {
        network: defaultNetwork.id,
    },
    deletionProtection: false,
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp

default_network = gcp.compute.Network("default", name="alloydb-cluster")
default = gcp.alloydb.Cluster("default",
    cluster_id="alloydb-cluster",
    location="us-central1",
    network_config={
        "network": default_network.id,
    },
    deletion_protection=False)
project = gcp.organizations.get_project()
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		defaultNetwork, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name: pulumi.String("alloydb-cluster"),
		})
		if err != nil {
			return err
		}
		_, err = alloydb.NewCluster(ctx, "default", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-cluster"),
			Location:  pulumi.String("us-central1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: defaultNetwork.ID(),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var defaultNetwork = new Gcp.Compute.Network("default", new()
    {
        Name = "alloydb-cluster",
    });

    var @default = new Gcp.Alloydb.Cluster("default", new()
    {
        ClusterId = "alloydb-cluster",
        Location = "us-central1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = defaultNetwork.Id,
        },
        DeletionProtection = false,
    });

    var project = Gcp.Organizations.GetProject.Invoke();

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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 defaultNetwork = new Network("defaultNetwork", NetworkArgs.builder()
            .name("alloydb-cluster")
            .build());

        var default_ = new Cluster("default", ClusterArgs.builder()
            .clusterId("alloydb-cluster")
            .location("us-central1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(defaultNetwork.id())
                .build())
            .deletionProtection(false)
            .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

    }
}
resources:
  default:
    type: gcp:alloydb:Cluster
    properties:
      clusterId: alloydb-cluster
      location: us-central1
      networkConfig:
        network: ${defaultNetwork.id}
      deletionProtection: false
  defaultNetwork:
    type: gcp:compute:Network
    name: default
    properties:
      name: alloydb-cluster
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The clusterId and location properties define the cluster’s identity and region. The networkConfig block connects the cluster to a VPC network where instances will run. This example creates a new network inline; production deployments typically reference existing networks. The cluster alone doesn’t run databases—you add Instance resources separately to handle workloads.

Configure automated and continuous backups

Production clusters need backup policies to protect against data loss through scheduled snapshots and point-in-time recovery.

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

const _default = new gcp.compute.Network("default", {name: "alloydb-cluster-full"});
const full = new gcp.alloydb.Cluster("full", {
    clusterId: "alloydb-cluster-full",
    location: "us-central1",
    networkConfig: {
        network: _default.id,
    },
    databaseVersion: "POSTGRES_15",
    initialUser: {
        user: "alloydb-cluster-full",
        password: "alloydb-cluster-full",
    },
    continuousBackupConfig: {
        enabled: true,
        recoveryWindowDays: 14,
    },
    automatedBackupPolicy: {
        location: "us-central1",
        backupWindow: "1800s",
        enabled: true,
        weeklySchedule: {
            daysOfWeeks: ["MONDAY"],
            startTimes: [{
                hours: 23,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            }],
        },
        quantityBasedRetention: {
            count: 1,
        },
        labels: {
            test: "alloydb-cluster-full",
        },
    },
    labels: {
        test: "alloydb-cluster-full",
    },
    deletionProtection: false,
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.Network("default", name="alloydb-cluster-full")
full = gcp.alloydb.Cluster("full",
    cluster_id="alloydb-cluster-full",
    location="us-central1",
    network_config={
        "network": default.id,
    },
    database_version="POSTGRES_15",
    initial_user={
        "user": "alloydb-cluster-full",
        "password": "alloydb-cluster-full",
    },
    continuous_backup_config={
        "enabled": True,
        "recovery_window_days": 14,
    },
    automated_backup_policy={
        "location": "us-central1",
        "backup_window": "1800s",
        "enabled": True,
        "weekly_schedule": {
            "days_of_weeks": ["MONDAY"],
            "start_times": [{
                "hours": 23,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            }],
        },
        "quantity_based_retention": {
            "count": 1,
        },
        "labels": {
            "test": "alloydb-cluster-full",
        },
    },
    labels={
        "test": "alloydb-cluster-full",
    },
    deletion_protection=False)
project = gcp.organizations.get_project()
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name: pulumi.String("alloydb-cluster-full"),
		})
		if err != nil {
			return err
		}
		_, err = alloydb.NewCluster(ctx, "full", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-cluster-full"),
			Location:  pulumi.String("us-central1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: _default.ID(),
			},
			DatabaseVersion: pulumi.String("POSTGRES_15"),
			InitialUser: &alloydb.ClusterInitialUserArgs{
				User:     pulumi.String("alloydb-cluster-full"),
				Password: pulumi.String("alloydb-cluster-full"),
			},
			ContinuousBackupConfig: &alloydb.ClusterContinuousBackupConfigArgs{
				Enabled:            pulumi.Bool(true),
				RecoveryWindowDays: pulumi.Int(14),
			},
			AutomatedBackupPolicy: &alloydb.ClusterAutomatedBackupPolicyArgs{
				Location:     pulumi.String("us-central1"),
				BackupWindow: pulumi.String("1800s"),
				Enabled:      pulumi.Bool(true),
				WeeklySchedule: &alloydb.ClusterAutomatedBackupPolicyWeeklyScheduleArgs{
					DaysOfWeeks: pulumi.StringArray{
						pulumi.String("MONDAY"),
					},
					StartTimes: alloydb.ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArray{
						&alloydb.ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArgs{
							Hours:   pulumi.Int(23),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
				QuantityBasedRetention: &alloydb.ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs{
					Count: pulumi.Int(1),
				},
				Labels: pulumi.StringMap{
					"test": pulumi.String("alloydb-cluster-full"),
				},
			},
			Labels: pulumi.StringMap{
				"test": pulumi.String("alloydb-cluster-full"),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Compute.Network("default", new()
    {
        Name = "alloydb-cluster-full",
    });

    var full = new Gcp.Alloydb.Cluster("full", new()
    {
        ClusterId = "alloydb-cluster-full",
        Location = "us-central1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = @default.Id,
        },
        DatabaseVersion = "POSTGRES_15",
        InitialUser = new Gcp.Alloydb.Inputs.ClusterInitialUserArgs
        {
            User = "alloydb-cluster-full",
            Password = "alloydb-cluster-full",
        },
        ContinuousBackupConfig = new Gcp.Alloydb.Inputs.ClusterContinuousBackupConfigArgs
        {
            Enabled = true,
            RecoveryWindowDays = 14,
        },
        AutomatedBackupPolicy = new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyArgs
        {
            Location = "us-central1",
            BackupWindow = "1800s",
            Enabled = true,
            WeeklySchedule = new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyWeeklyScheduleArgs
            {
                DaysOfWeeks = new[]
                {
                    "MONDAY",
                },
                StartTimes = new[]
                {
                    new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArgs
                    {
                        Hours = 23,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
            QuantityBasedRetention = new Gcp.Alloydb.Inputs.ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs
            {
                Count = 1,
            },
            Labels = 
            {
                { "test", "alloydb-cluster-full" },
            },
        },
        Labels = 
        {
            { "test", "alloydb-cluster-full" },
        },
        DeletionProtection = false,
    });

    var project = Gcp.Organizations.GetProject.Invoke();

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterInitialUserArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterContinuousBackupConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterAutomatedBackupPolicyArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterAutomatedBackupPolicyWeeklyScheduleArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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 Network("default", NetworkArgs.builder()
            .name("alloydb-cluster-full")
            .build());

        var full = new Cluster("full", ClusterArgs.builder()
            .clusterId("alloydb-cluster-full")
            .location("us-central1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(default_.id())
                .build())
            .databaseVersion("POSTGRES_15")
            .initialUser(ClusterInitialUserArgs.builder()
                .user("alloydb-cluster-full")
                .password("alloydb-cluster-full")
                .build())
            .continuousBackupConfig(ClusterContinuousBackupConfigArgs.builder()
                .enabled(true)
                .recoveryWindowDays(14)
                .build())
            .automatedBackupPolicy(ClusterAutomatedBackupPolicyArgs.builder()
                .location("us-central1")
                .backupWindow("1800s")
                .enabled(true)
                .weeklySchedule(ClusterAutomatedBackupPolicyWeeklyScheduleArgs.builder()
                    .daysOfWeeks("MONDAY")
                    .startTimes(ClusterAutomatedBackupPolicyWeeklyScheduleStartTimeArgs.builder()
                        .hours(23)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .quantityBasedRetention(ClusterAutomatedBackupPolicyQuantityBasedRetentionArgs.builder()
                    .count(1)
                    .build())
                .labels(Map.of("test", "alloydb-cluster-full"))
                .build())
            .labels(Map.of("test", "alloydb-cluster-full"))
            .deletionProtection(false)
            .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

    }
}
resources:
  full:
    type: gcp:alloydb:Cluster
    properties:
      clusterId: alloydb-cluster-full
      location: us-central1
      networkConfig:
        network: ${default.id}
      databaseVersion: POSTGRES_15
      initialUser:
        user: alloydb-cluster-full
        password: alloydb-cluster-full
      continuousBackupConfig:
        enabled: true
        recoveryWindowDays: 14
      automatedBackupPolicy:
        location: us-central1
        backupWindow: 1800s
        enabled: true
        weeklySchedule:
          daysOfWeeks:
            - MONDAY
          startTimes:
            - hours: 23
              minutes: 0
              seconds: 0
              nanos: 0
        quantityBasedRetention:
          count: 1
        labels:
          test: alloydb-cluster-full
      labels:
        test: alloydb-cluster-full
      deletionProtection: false
  default:
    type: gcp:compute:Network
    properties:
      name: alloydb-cluster-full
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The automatedBackupPolicy block schedules regular backups with weeklySchedule defining when backups run and quantityBasedRetention controlling how many to keep. The continuousBackupConfig block enables point-in-time recovery with recoveryWindowDays setting how far back you can restore. Together, these provide both scheduled snapshots and continuous protection.

Restore clusters from backups or point-in-time

Disaster recovery workflows create new clusters from existing backup snapshots or restore to specific timestamps.

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

const _default = gcp.compute.getNetwork({
    name: "alloydb-network",
});
const source = new gcp.alloydb.Cluster("source", {
    clusterId: "alloydb-source-cluster",
    location: "us-central1",
    network: _default.then(_default => _default.id),
    initialUser: {
        password: "alloydb-source-cluster",
    },
    deletionProtection: false,
});
const privateIpAlloc = new gcp.compute.GlobalAddress("private_ip_alloc", {
    name: "alloydb-source-cluster",
    addressType: "INTERNAL",
    purpose: "VPC_PEERING",
    prefixLength: 16,
    network: _default.then(_default => _default.id),
});
const vpcConnection = new gcp.servicenetworking.Connection("vpc_connection", {
    network: _default.then(_default => _default.id),
    service: "servicenetworking.googleapis.com",
    reservedPeeringRanges: [privateIpAlloc.name],
});
const sourceInstance = new gcp.alloydb.Instance("source", {
    cluster: source.name,
    instanceId: "alloydb-instance",
    instanceType: "PRIMARY",
    machineConfig: {
        cpuCount: 2,
    },
}, {
    dependsOn: [vpcConnection],
});
const sourceBackup = new gcp.alloydb.Backup("source", {
    backupId: "alloydb-backup",
    location: "us-central1",
    clusterName: source.name,
}, {
    dependsOn: [sourceInstance],
});
const restoredFromBackup = new gcp.alloydb.Cluster("restored_from_backup", {
    clusterId: "alloydb-backup-restored",
    location: "us-central1",
    networkConfig: {
        network: _default.then(_default => _default.id),
    },
    restoreBackupSource: {
        backupName: sourceBackup.name,
    },
    deletionProtection: false,
});
const restoredViaPitr = new gcp.alloydb.Cluster("restored_via_pitr", {
    clusterId: "alloydb-pitr-restored",
    location: "us-central1",
    networkConfig: {
        network: _default.then(_default => _default.id),
    },
    restoreContinuousBackupSource: {
        cluster: source.name,
        pointInTime: "2023-08-03T19:19:00.094Z",
    },
    deletionProtection: false,
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.get_network(name="alloydb-network")
source = gcp.alloydb.Cluster("source",
    cluster_id="alloydb-source-cluster",
    location="us-central1",
    network=default.id,
    initial_user={
        "password": "alloydb-source-cluster",
    },
    deletion_protection=False)
private_ip_alloc = gcp.compute.GlobalAddress("private_ip_alloc",
    name="alloydb-source-cluster",
    address_type="INTERNAL",
    purpose="VPC_PEERING",
    prefix_length=16,
    network=default.id)
vpc_connection = gcp.servicenetworking.Connection("vpc_connection",
    network=default.id,
    service="servicenetworking.googleapis.com",
    reserved_peering_ranges=[private_ip_alloc.name])
source_instance = gcp.alloydb.Instance("source",
    cluster=source.name,
    instance_id="alloydb-instance",
    instance_type="PRIMARY",
    machine_config={
        "cpu_count": 2,
    },
    opts = pulumi.ResourceOptions(depends_on=[vpc_connection]))
source_backup = gcp.alloydb.Backup("source",
    backup_id="alloydb-backup",
    location="us-central1",
    cluster_name=source.name,
    opts = pulumi.ResourceOptions(depends_on=[source_instance]))
restored_from_backup = gcp.alloydb.Cluster("restored_from_backup",
    cluster_id="alloydb-backup-restored",
    location="us-central1",
    network_config={
        "network": default.id,
    },
    restore_backup_source={
        "backup_name": source_backup.name,
    },
    deletion_protection=False)
restored_via_pitr = gcp.alloydb.Cluster("restored_via_pitr",
    cluster_id="alloydb-pitr-restored",
    location="us-central1",
    network_config={
        "network": default.id,
    },
    restore_continuous_backup_source={
        "cluster": source.name,
        "point_in_time": "2023-08-03T19:19:00.094Z",
    },
    deletion_protection=False)
project = gcp.organizations.get_project()
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := compute.LookupNetwork(ctx, &compute.LookupNetworkArgs{
			Name: "alloydb-network",
		}, nil)
		if err != nil {
			return err
		}
		source, err := alloydb.NewCluster(ctx, "source", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-source-cluster"),
			Location:  pulumi.String("us-central1"),
			Network:   _default.Id,
			InitialUser: &alloydb.ClusterInitialUserArgs{
				Password: pulumi.String("alloydb-source-cluster"),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		privateIpAlloc, err := compute.NewGlobalAddress(ctx, "private_ip_alloc", &compute.GlobalAddressArgs{
			Name:         pulumi.String("alloydb-source-cluster"),
			AddressType:  pulumi.String("INTERNAL"),
			Purpose:      pulumi.String("VPC_PEERING"),
			PrefixLength: pulumi.Int(16),
			Network:      pulumi.String(_default.Id),
		})
		if err != nil {
			return err
		}
		vpcConnection, err := servicenetworking.NewConnection(ctx, "vpc_connection", &servicenetworking.ConnectionArgs{
			Network: pulumi.String(_default.Id),
			Service: pulumi.String("servicenetworking.googleapis.com"),
			ReservedPeeringRanges: pulumi.StringArray{
				privateIpAlloc.Name,
			},
		})
		if err != nil {
			return err
		}
		sourceInstance, err := alloydb.NewInstance(ctx, "source", &alloydb.InstanceArgs{
			Cluster:      source.Name,
			InstanceId:   pulumi.String("alloydb-instance"),
			InstanceType: pulumi.String("PRIMARY"),
			MachineConfig: &alloydb.InstanceMachineConfigArgs{
				CpuCount: pulumi.Int(2),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			vpcConnection,
		}))
		if err != nil {
			return err
		}
		sourceBackup, err := alloydb.NewBackup(ctx, "source", &alloydb.BackupArgs{
			BackupId:    pulumi.String("alloydb-backup"),
			Location:    pulumi.String("us-central1"),
			ClusterName: source.Name,
		}, pulumi.DependsOn([]pulumi.Resource{
			sourceInstance,
		}))
		if err != nil {
			return err
		}
		_, err = alloydb.NewCluster(ctx, "restored_from_backup", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-backup-restored"),
			Location:  pulumi.String("us-central1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: pulumi.String(_default.Id),
			},
			RestoreBackupSource: &alloydb.ClusterRestoreBackupSourceArgs{
				BackupName: sourceBackup.Name,
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = alloydb.NewCluster(ctx, "restored_via_pitr", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-pitr-restored"),
			Location:  pulumi.String("us-central1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: pulumi.String(_default.Id),
			},
			RestoreContinuousBackupSource: &alloydb.ClusterRestoreContinuousBackupSourceArgs{
				Cluster:     source.Name,
				PointInTime: pulumi.String("2023-08-03T19:19:00.094Z"),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = Gcp.Compute.GetNetwork.Invoke(new()
    {
        Name = "alloydb-network",
    });

    var source = new Gcp.Alloydb.Cluster("source", new()
    {
        ClusterId = "alloydb-source-cluster",
        Location = "us-central1",
        Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
        InitialUser = new Gcp.Alloydb.Inputs.ClusterInitialUserArgs
        {
            Password = "alloydb-source-cluster",
        },
        DeletionProtection = false,
    });

    var privateIpAlloc = new Gcp.Compute.GlobalAddress("private_ip_alloc", new()
    {
        Name = "alloydb-source-cluster",
        AddressType = "INTERNAL",
        Purpose = "VPC_PEERING",
        PrefixLength = 16,
        Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
    });

    var vpcConnection = new Gcp.ServiceNetworking.Connection("vpc_connection", new()
    {
        Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
        Service = "servicenetworking.googleapis.com",
        ReservedPeeringRanges = new[]
        {
            privateIpAlloc.Name,
        },
    });

    var sourceInstance = new Gcp.Alloydb.Instance("source", new()
    {
        Cluster = source.Name,
        InstanceId = "alloydb-instance",
        InstanceType = "PRIMARY",
        MachineConfig = new Gcp.Alloydb.Inputs.InstanceMachineConfigArgs
        {
            CpuCount = 2,
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            vpcConnection,
        },
    });

    var sourceBackup = new Gcp.Alloydb.Backup("source", new()
    {
        BackupId = "alloydb-backup",
        Location = "us-central1",
        ClusterName = source.Name,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            sourceInstance,
        },
    });

    var restoredFromBackup = new Gcp.Alloydb.Cluster("restored_from_backup", new()
    {
        ClusterId = "alloydb-backup-restored",
        Location = "us-central1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
        },
        RestoreBackupSource = new Gcp.Alloydb.Inputs.ClusterRestoreBackupSourceArgs
        {
            BackupName = sourceBackup.Name,
        },
        DeletionProtection = false,
    });

    var restoredViaPitr = new Gcp.Alloydb.Cluster("restored_via_pitr", new()
    {
        ClusterId = "alloydb-pitr-restored",
        Location = "us-central1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = @default.Apply(@default => @default.Apply(getNetworkResult => getNetworkResult.Id)),
        },
        RestoreContinuousBackupSource = new Gcp.Alloydb.Inputs.ClusterRestoreContinuousBackupSourceArgs
        {
            Cluster = source.Name,
            PointInTime = "2023-08-03T19:19:00.094Z",
        },
        DeletionProtection = false,
    });

    var project = Gcp.Organizations.GetProject.Invoke();

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.ComputeFunctions;
import com.pulumi.gcp.compute.inputs.GetNetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterInitialUserArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.alloydb.Instance;
import com.pulumi.gcp.alloydb.InstanceArgs;
import com.pulumi.gcp.alloydb.inputs.InstanceMachineConfigArgs;
import com.pulumi.gcp.alloydb.Backup;
import com.pulumi.gcp.alloydb.BackupArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterRestoreBackupSourceArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterRestoreContinuousBackupSourceArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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) {
        final var default = ComputeFunctions.getNetwork(GetNetworkArgs.builder()
            .name("alloydb-network")
            .build());

        var source = new Cluster("source", ClusterArgs.builder()
            .clusterId("alloydb-source-cluster")
            .location("us-central1")
            .network(default_.id())
            .initialUser(ClusterInitialUserArgs.builder()
                .password("alloydb-source-cluster")
                .build())
            .deletionProtection(false)
            .build());

        var privateIpAlloc = new GlobalAddress("privateIpAlloc", GlobalAddressArgs.builder()
            .name("alloydb-source-cluster")
            .addressType("INTERNAL")
            .purpose("VPC_PEERING")
            .prefixLength(16)
            .network(default_.id())
            .build());

        var vpcConnection = new Connection("vpcConnection", ConnectionArgs.builder()
            .network(default_.id())
            .service("servicenetworking.googleapis.com")
            .reservedPeeringRanges(privateIpAlloc.name())
            .build());

        var sourceInstance = new Instance("sourceInstance", InstanceArgs.builder()
            .cluster(source.name())
            .instanceId("alloydb-instance")
            .instanceType("PRIMARY")
            .machineConfig(InstanceMachineConfigArgs.builder()
                .cpuCount(2)
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(vpcConnection)
                .build());

        var sourceBackup = new Backup("sourceBackup", BackupArgs.builder()
            .backupId("alloydb-backup")
            .location("us-central1")
            .clusterName(source.name())
            .build(), CustomResourceOptions.builder()
                .dependsOn(sourceInstance)
                .build());

        var restoredFromBackup = new Cluster("restoredFromBackup", ClusterArgs.builder()
            .clusterId("alloydb-backup-restored")
            .location("us-central1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(default_.id())
                .build())
            .restoreBackupSource(ClusterRestoreBackupSourceArgs.builder()
                .backupName(sourceBackup.name())
                .build())
            .deletionProtection(false)
            .build());

        var restoredViaPitr = new Cluster("restoredViaPitr", ClusterArgs.builder()
            .clusterId("alloydb-pitr-restored")
            .location("us-central1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(default_.id())
                .build())
            .restoreContinuousBackupSource(ClusterRestoreContinuousBackupSourceArgs.builder()
                .cluster(source.name())
                .pointInTime("2023-08-03T19:19:00.094Z")
                .build())
            .deletionProtection(false)
            .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

    }
}
resources:
  source:
    type: gcp:alloydb:Cluster
    properties:
      clusterId: alloydb-source-cluster
      location: us-central1
      network: ${default.id}
      initialUser:
        password: alloydb-source-cluster
      deletionProtection: false
  sourceInstance:
    type: gcp:alloydb:Instance
    name: source
    properties:
      cluster: ${source.name}
      instanceId: alloydb-instance
      instanceType: PRIMARY
      machineConfig:
        cpuCount: 2
    options:
      dependsOn:
        - ${vpcConnection}
  sourceBackup:
    type: gcp:alloydb:Backup
    name: source
    properties:
      backupId: alloydb-backup
      location: us-central1
      clusterName: ${source.name}
    options:
      dependsOn:
        - ${sourceInstance}
  restoredFromBackup:
    type: gcp:alloydb:Cluster
    name: restored_from_backup
    properties:
      clusterId: alloydb-backup-restored
      location: us-central1
      networkConfig:
        network: ${default.id}
      restoreBackupSource:
        backupName: ${sourceBackup.name}
      deletionProtection: false
  restoredViaPitr:
    type: gcp:alloydb:Cluster
    name: restored_via_pitr
    properties:
      clusterId: alloydb-pitr-restored
      location: us-central1
      networkConfig:
        network: ${default.id}
      restoreContinuousBackupSource:
        cluster: ${source.name}
        pointInTime: 2023-08-03T19:19:00.094Z
      deletionProtection: false
  privateIpAlloc:
    type: gcp:compute:GlobalAddress
    name: private_ip_alloc
    properties:
      name: alloydb-source-cluster
      addressType: INTERNAL
      purpose: VPC_PEERING
      prefixLength: 16
      network: ${default.id}
  vpcConnection:
    type: gcp:servicenetworking:Connection
    name: vpc_connection
    properties:
      network: ${default.id}
      service: servicenetworking.googleapis.com
      reservedPeeringRanges:
        - ${privateIpAlloc.name}
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}
  default:
    fn::invoke:
      function: gcp:compute:getNetwork
      arguments:
        name: alloydb-network

The restoreBackupSource block creates a cluster from a named backup snapshot, while restoreContinuousBackupSource restores to a specific pointInTime timestamp from continuous backup data. These are mutually exclusive—use one or the other depending on your recovery scenario. Both require VPC peering setup (GlobalAddress and Connection resources) and reference source clusters that must exist first.

Deploy secondary clusters for cross-region replication

High-availability architectures replicate data across regions using secondary clusters that sync continuously from a primary.

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

const _default = new gcp.compute.Network("default", {name: "alloydb-secondary-cluster"});
const primary = new gcp.alloydb.Cluster("primary", {
    clusterId: "alloydb-primary-cluster",
    location: "us-central1",
    networkConfig: {
        network: _default.id,
    },
    deletionProtection: false,
});
const privateIpAlloc = new gcp.compute.GlobalAddress("private_ip_alloc", {
    name: "alloydb-secondary-cluster",
    addressType: "INTERNAL",
    purpose: "VPC_PEERING",
    prefixLength: 16,
    network: _default.id,
});
const vpcConnection = new gcp.servicenetworking.Connection("vpc_connection", {
    network: _default.id,
    service: "servicenetworking.googleapis.com",
    reservedPeeringRanges: [privateIpAlloc.name],
});
const primaryInstance = new gcp.alloydb.Instance("primary", {
    cluster: primary.name,
    instanceId: "alloydb-primary-instance",
    instanceType: "PRIMARY",
    machineConfig: {
        cpuCount: 2,
    },
}, {
    dependsOn: [vpcConnection],
});
const secondary = new gcp.alloydb.Cluster("secondary", {
    clusterId: "alloydb-secondary-cluster",
    location: "us-east1",
    networkConfig: {
        network: _default.id,
    },
    clusterType: "SECONDARY",
    continuousBackupConfig: {
        enabled: false,
    },
    secondaryConfig: {
        primaryClusterName: primary.name,
    },
    deletionProtection: false,
}, {
    dependsOn: [primaryInstance],
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp

default = gcp.compute.Network("default", name="alloydb-secondary-cluster")
primary = gcp.alloydb.Cluster("primary",
    cluster_id="alloydb-primary-cluster",
    location="us-central1",
    network_config={
        "network": default.id,
    },
    deletion_protection=False)
private_ip_alloc = gcp.compute.GlobalAddress("private_ip_alloc",
    name="alloydb-secondary-cluster",
    address_type="INTERNAL",
    purpose="VPC_PEERING",
    prefix_length=16,
    network=default.id)
vpc_connection = gcp.servicenetworking.Connection("vpc_connection",
    network=default.id,
    service="servicenetworking.googleapis.com",
    reserved_peering_ranges=[private_ip_alloc.name])
primary_instance = gcp.alloydb.Instance("primary",
    cluster=primary.name,
    instance_id="alloydb-primary-instance",
    instance_type="PRIMARY",
    machine_config={
        "cpu_count": 2,
    },
    opts = pulumi.ResourceOptions(depends_on=[vpc_connection]))
secondary = gcp.alloydb.Cluster("secondary",
    cluster_id="alloydb-secondary-cluster",
    location="us-east1",
    network_config={
        "network": default.id,
    },
    cluster_type="SECONDARY",
    continuous_backup_config={
        "enabled": False,
    },
    secondary_config={
        "primary_cluster_name": primary.name,
    },
    deletion_protection=False,
    opts = pulumi.ResourceOptions(depends_on=[primary_instance]))
project = gcp.organizations.get_project()
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/alloydb"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_default, err := compute.NewNetwork(ctx, "default", &compute.NetworkArgs{
			Name: pulumi.String("alloydb-secondary-cluster"),
		})
		if err != nil {
			return err
		}
		primary, err := alloydb.NewCluster(ctx, "primary", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-primary-cluster"),
			Location:  pulumi.String("us-central1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: _default.ID(),
			},
			DeletionProtection: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		privateIpAlloc, err := compute.NewGlobalAddress(ctx, "private_ip_alloc", &compute.GlobalAddressArgs{
			Name:         pulumi.String("alloydb-secondary-cluster"),
			AddressType:  pulumi.String("INTERNAL"),
			Purpose:      pulumi.String("VPC_PEERING"),
			PrefixLength: pulumi.Int(16),
			Network:      _default.ID(),
		})
		if err != nil {
			return err
		}
		vpcConnection, err := servicenetworking.NewConnection(ctx, "vpc_connection", &servicenetworking.ConnectionArgs{
			Network: _default.ID(),
			Service: pulumi.String("servicenetworking.googleapis.com"),
			ReservedPeeringRanges: pulumi.StringArray{
				privateIpAlloc.Name,
			},
		})
		if err != nil {
			return err
		}
		primaryInstance, err := alloydb.NewInstance(ctx, "primary", &alloydb.InstanceArgs{
			Cluster:      primary.Name,
			InstanceId:   pulumi.String("alloydb-primary-instance"),
			InstanceType: pulumi.String("PRIMARY"),
			MachineConfig: &alloydb.InstanceMachineConfigArgs{
				CpuCount: pulumi.Int(2),
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			vpcConnection,
		}))
		if err != nil {
			return err
		}
		_, err = alloydb.NewCluster(ctx, "secondary", &alloydb.ClusterArgs{
			ClusterId: pulumi.String("alloydb-secondary-cluster"),
			Location:  pulumi.String("us-east1"),
			NetworkConfig: &alloydb.ClusterNetworkConfigArgs{
				Network: _default.ID(),
			},
			ClusterType: pulumi.String("SECONDARY"),
			ContinuousBackupConfig: &alloydb.ClusterContinuousBackupConfigArgs{
				Enabled: pulumi.Bool(false),
			},
			SecondaryConfig: &alloydb.ClusterSecondaryConfigArgs{
				PrimaryClusterName: primary.Name,
			},
			DeletionProtection: pulumi.Bool(false),
		}, pulumi.DependsOn([]pulumi.Resource{
			primaryInstance,
		}))
		if err != nil {
			return err
		}
		_, err = organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var @default = new Gcp.Compute.Network("default", new()
    {
        Name = "alloydb-secondary-cluster",
    });

    var primary = new Gcp.Alloydb.Cluster("primary", new()
    {
        ClusterId = "alloydb-primary-cluster",
        Location = "us-central1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = @default.Id,
        },
        DeletionProtection = false,
    });

    var privateIpAlloc = new Gcp.Compute.GlobalAddress("private_ip_alloc", new()
    {
        Name = "alloydb-secondary-cluster",
        AddressType = "INTERNAL",
        Purpose = "VPC_PEERING",
        PrefixLength = 16,
        Network = @default.Id,
    });

    var vpcConnection = new Gcp.ServiceNetworking.Connection("vpc_connection", new()
    {
        Network = @default.Id,
        Service = "servicenetworking.googleapis.com",
        ReservedPeeringRanges = new[]
        {
            privateIpAlloc.Name,
        },
    });

    var primaryInstance = new Gcp.Alloydb.Instance("primary", new()
    {
        Cluster = primary.Name,
        InstanceId = "alloydb-primary-instance",
        InstanceType = "PRIMARY",
        MachineConfig = new Gcp.Alloydb.Inputs.InstanceMachineConfigArgs
        {
            CpuCount = 2,
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            vpcConnection,
        },
    });

    var secondary = new Gcp.Alloydb.Cluster("secondary", new()
    {
        ClusterId = "alloydb-secondary-cluster",
        Location = "us-east1",
        NetworkConfig = new Gcp.Alloydb.Inputs.ClusterNetworkConfigArgs
        {
            Network = @default.Id,
        },
        ClusterType = "SECONDARY",
        ContinuousBackupConfig = new Gcp.Alloydb.Inputs.ClusterContinuousBackupConfigArgs
        {
            Enabled = false,
        },
        SecondaryConfig = new Gcp.Alloydb.Inputs.ClusterSecondaryConfigArgs
        {
            PrimaryClusterName = primary.Name,
        },
        DeletionProtection = false,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            primaryInstance,
        },
    });

    var project = Gcp.Organizations.GetProject.Invoke();

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.alloydb.Cluster;
import com.pulumi.gcp.alloydb.ClusterArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterNetworkConfigArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.alloydb.Instance;
import com.pulumi.gcp.alloydb.InstanceArgs;
import com.pulumi.gcp.alloydb.inputs.InstanceMachineConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterContinuousBackupConfigArgs;
import com.pulumi.gcp.alloydb.inputs.ClusterSecondaryConfigArgs;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
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 default_ = new Network("default", NetworkArgs.builder()
            .name("alloydb-secondary-cluster")
            .build());

        var primary = new Cluster("primary", ClusterArgs.builder()
            .clusterId("alloydb-primary-cluster")
            .location("us-central1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(default_.id())
                .build())
            .deletionProtection(false)
            .build());

        var privateIpAlloc = new GlobalAddress("privateIpAlloc", GlobalAddressArgs.builder()
            .name("alloydb-secondary-cluster")
            .addressType("INTERNAL")
            .purpose("VPC_PEERING")
            .prefixLength(16)
            .network(default_.id())
            .build());

        var vpcConnection = new Connection("vpcConnection", ConnectionArgs.builder()
            .network(default_.id())
            .service("servicenetworking.googleapis.com")
            .reservedPeeringRanges(privateIpAlloc.name())
            .build());

        var primaryInstance = new Instance("primaryInstance", InstanceArgs.builder()
            .cluster(primary.name())
            .instanceId("alloydb-primary-instance")
            .instanceType("PRIMARY")
            .machineConfig(InstanceMachineConfigArgs.builder()
                .cpuCount(2)
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(vpcConnection)
                .build());

        var secondary = new Cluster("secondary", ClusterArgs.builder()
            .clusterId("alloydb-secondary-cluster")
            .location("us-east1")
            .networkConfig(ClusterNetworkConfigArgs.builder()
                .network(default_.id())
                .build())
            .clusterType("SECONDARY")
            .continuousBackupConfig(ClusterContinuousBackupConfigArgs.builder()
                .enabled(false)
                .build())
            .secondaryConfig(ClusterSecondaryConfigArgs.builder()
                .primaryClusterName(primary.name())
                .build())
            .deletionProtection(false)
            .build(), CustomResourceOptions.builder()
                .dependsOn(primaryInstance)
                .build());

        final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
            .build());

    }
}
resources:
  primary:
    type: gcp:alloydb:Cluster
    properties:
      clusterId: alloydb-primary-cluster
      location: us-central1
      networkConfig:
        network: ${default.id}
      deletionProtection: false
  primaryInstance:
    type: gcp:alloydb:Instance
    name: primary
    properties:
      cluster: ${primary.name}
      instanceId: alloydb-primary-instance
      instanceType: PRIMARY
      machineConfig:
        cpuCount: 2
    options:
      dependsOn:
        - ${vpcConnection}
  secondary:
    type: gcp:alloydb:Cluster
    properties:
      clusterId: alloydb-secondary-cluster
      location: us-east1
      networkConfig:
        network: ${default.id}
      clusterType: SECONDARY
      continuousBackupConfig:
        enabled: false
      secondaryConfig:
        primaryClusterName: ${primary.name}
      deletionProtection: false
    options:
      dependsOn:
        - ${primaryInstance}
  default:
    type: gcp:compute:Network
    properties:
      name: alloydb-secondary-cluster
  privateIpAlloc:
    type: gcp:compute:GlobalAddress
    name: private_ip_alloc
    properties:
      name: alloydb-secondary-cluster
      addressType: INTERNAL
      purpose: VPC_PEERING
      prefixLength: 16
      network: ${default.id}
  vpcConnection:
    type: gcp:servicenetworking:Connection
    name: vpc_connection
    properties:
      network: ${default.id}
      service: servicenetworking.googleapis.com
      reservedPeeringRanges:
        - ${privateIpAlloc.name}
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The clusterType property set to SECONDARY designates this as a replica cluster. The secondaryConfig block points to the primaryClusterName to establish replication. Secondary clusters require the primary to have at least one running instance and need VPC peering for cross-region connectivity. Continuous backup is typically disabled on secondaries since they replicate from the primary’s backup data.

Beyond these examples

These snippets focus on specific cluster-level features: cluster creation and network placement, backup policies and disaster recovery, and cross-region replication. They’re intentionally minimal rather than full database deployments.

The examples may reference pre-existing infrastructure such as VPC networks (or create them inline in basic examples), VPC peering configuration (GlobalAddress and Connection resources), and source clusters and backups for restore scenarios. They focus on configuring the cluster container rather than provisioning complete database systems.

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

  • Database version upgrades (databaseVersion property)
  • Customer-managed encryption keys (encryptionConfig)
  • Maintenance windows and update policies
  • Private Service Connect configuration (pscConfig)
  • Initial user credentials (initialUser block)
  • Instance provisioning (requires separate Instance resources)

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

Let's deploy GCP AlloyDB Clusters

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Cluster Types & Configuration
What's the difference between PRIMARY and SECONDARY clusters?
PRIMARY clusters are the default type for standard deployments. SECONDARY clusters are used for cross-region replication and require clusterType = "SECONDARY", a secondaryConfig with the primary cluster name, and continuousBackupConfig.enabled = false.
What properties are immutable after cluster creation?
You cannot change clusterId, location, project, restoreBackupSource, or restoreContinuousBackupSource after creating the cluster.
Do I need to configure a VPC network for my cluster?
Yes, networkConfig with a network ID is required for all clusters.
Backup & Recovery
What's the default backup policy for AlloyDB clusters?
Automated backups are disabled by default. Continuous backup is enabled by default with a policy that takes one backup daily and retains backups for 14 days.
How do I configure automated backups?
Set automatedBackupPolicy with location, backupWindow, weeklySchedule (days and start times), and retention settings (quantityBasedRetention or time-based).
How do I restore a cluster from a backup?
Use restoreBackupSource with the backup name when creating the cluster. This conflicts with restoreContinuousBackupSource, so you can only use one restore method.
How do I restore a cluster using point-in-time recovery?
Use restoreContinuousBackupSource with the source cluster name and pointInTime timestamp. This conflicts with restoreBackupSource, so you can only use one restore method.
Database Upgrades & Versioning
Can I downgrade my cluster's database version?
No. Changing databaseVersion to a higher version upgrades the cluster irreversibly. Downgrades are not supported.
Does Pulumi wait for major version upgrades to complete?
By default, no. The skipAwaitMajorVersionUpgrade property defaults to true. Set it to false if you want Pulumi to wait for the upgrade to finish.
Deletion & Lifecycle
How do I delete a secondary cluster with instances?
You must set deletionPolicy = "FORCE" to delete a secondary cluster that has instances. Without this, deletion returns an error because there’s no support for deleting just the secondary instance.
What does deletionProtection do?
When enabled, deletionProtection prevents accidental deletion of the cluster. Set it to false to allow deletion.
Labels & Annotations
Why don't my labels and annotations show all values on the resource?
The labels and annotations fields are non-authoritative and only manage values in your configuration. Use effectiveLabels and effectiveAnnotations to see all labels/annotations on the resource, including those set by other clients or services.

Using a different cloud?

Explore database guides for other cloud providers: