Deploy GCP Cloud Memorystore Redis Clusters

The gcp:redis/cluster:Cluster resource, part of the Pulumi GCP provider, provisions a Google Cloud Memorystore Redis Cluster: a managed, distributed Redis deployment with configurable sharding, replication, and persistence. This guide focuses on four capabilities: high availability with zone distribution, cross-region replication for disaster recovery, persistence strategies (RDB and AOF), and customer-managed encryption keys.

Redis clusters require VPC networks with ServiceConnectionPolicy for Private Service Connect connectivity. They may also reference KMS keys for encryption or other clusters for cross-region replication. The examples are intentionally small. Combine them with your own network infrastructure and security policies.

Deploy a multi-zone cluster with high availability

Most Redis deployments start with a highly available cluster that distributes shards across multiple zones to survive zone failures.

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

const consumerNet = new gcp.compute.Network("consumer_net", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const consumerSubnet = new gcp.compute.Subnetwork("consumer_subnet", {
    name: "my-subnet",
    ipCidrRange: "10.0.0.248/29",
    region: "us-central1",
    network: consumerNet.id,
});
const _default = new gcp.networkconnectivity.ServiceConnectionPolicy("default", {
    name: "my-policy",
    location: "us-central1",
    serviceClass: "gcp-memorystore-redis",
    description: "my basic service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [consumerSubnet.id],
    },
});
const cluster_ha = new gcp.redis.Cluster("cluster-ha", {
    name: "ha-cluster",
    shardCount: 3,
    pscConfigs: [{
        network: consumerNet.id,
    }],
    region: "us-central1",
    replicaCount: 1,
    nodeType: "REDIS_SHARED_CORE_NANO",
    transitEncryptionMode: "TRANSIT_ENCRYPTION_MODE_DISABLED",
    authorizationMode: "AUTH_MODE_DISABLED",
    redisConfigs: {
        "maxmemory-policy": "volatile-ttl",
    },
    deletionProtectionEnabled: true,
    zoneDistributionConfig: {
        mode: "MULTI_ZONE",
    },
    maintenancePolicy: {
        weeklyMaintenanceWindows: [{
            day: "MONDAY",
            startTime: {
                hours: 1,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            },
        }],
    },
}, {
    dependsOn: [_default],
});
import pulumi
import pulumi_gcp as gcp

consumer_net = gcp.compute.Network("consumer_net",
    name="my-network",
    auto_create_subnetworks=False)
consumer_subnet = gcp.compute.Subnetwork("consumer_subnet",
    name="my-subnet",
    ip_cidr_range="10.0.0.248/29",
    region="us-central1",
    network=consumer_net.id)
default = gcp.networkconnectivity.ServiceConnectionPolicy("default",
    name="my-policy",
    location="us-central1",
    service_class="gcp-memorystore-redis",
    description="my basic service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [consumer_subnet.id],
    })
cluster_ha = gcp.redis.Cluster("cluster-ha",
    name="ha-cluster",
    shard_count=3,
    psc_configs=[{
        "network": consumer_net.id,
    }],
    region="us-central1",
    replica_count=1,
    node_type="REDIS_SHARED_CORE_NANO",
    transit_encryption_mode="TRANSIT_ENCRYPTION_MODE_DISABLED",
    authorization_mode="AUTH_MODE_DISABLED",
    redis_configs={
        "maxmemory-policy": "volatile-ttl",
    },
    deletion_protection_enabled=True,
    zone_distribution_config={
        "mode": "MULTI_ZONE",
    },
    maintenance_policy={
        "weekly_maintenance_windows": [{
            "day": "MONDAY",
            "start_time": {
                "hours": 1,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            },
        }],
    },
    opts = pulumi.ResourceOptions(depends_on=[default]))
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		consumerNet, err := compute.NewNetwork(ctx, "consumer_net", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		consumerSubnet, err := compute.NewSubnetwork(ctx, "consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("my-subnet"),
			IpCidrRange: pulumi.String("10.0.0.248/29"),
			Region:      pulumi.String("us-central1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		_default, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "default", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("my-policy"),
			Location:     pulumi.String("us-central1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("my basic service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					consumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = redis.NewCluster(ctx, "cluster-ha", &redis.ClusterArgs{
			Name:       pulumi.String("ha-cluster"),
			ShardCount: pulumi.Int(3),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			Region:                pulumi.String("us-central1"),
			ReplicaCount:          pulumi.Int(1),
			NodeType:              pulumi.String("REDIS_SHARED_CORE_NANO"),
			TransitEncryptionMode: pulumi.String("TRANSIT_ENCRYPTION_MODE_DISABLED"),
			AuthorizationMode:     pulumi.String("AUTH_MODE_DISABLED"),
			RedisConfigs: pulumi.StringMap{
				"maxmemory-policy": pulumi.String("volatile-ttl"),
			},
			DeletionProtectionEnabled: pulumi.Bool(true),
			ZoneDistributionConfig: &redis.ClusterZoneDistributionConfigArgs{
				Mode: pulumi.String("MULTI_ZONE"),
			},
			MaintenancePolicy: &redis.ClusterMaintenancePolicyArgs{
				WeeklyMaintenanceWindows: redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArray{
					&redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs{
						Day: pulumi.String("MONDAY"),
						StartTime: &redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs{
							Hours:   pulumi.Int(1),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			_default,
		}))
		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 consumerNet = new Gcp.Compute.Network("consumer_net", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var consumerSubnet = new Gcp.Compute.Subnetwork("consumer_subnet", new()
    {
        Name = "my-subnet",
        IpCidrRange = "10.0.0.248/29",
        Region = "us-central1",
        Network = consumerNet.Id,
    });

    var @default = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("default", new()
    {
        Name = "my-policy",
        Location = "us-central1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "my basic service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                consumerSubnet.Id,
            },
        },
    });

    var cluster_ha = new Gcp.Redis.Cluster("cluster-ha", new()
    {
        Name = "ha-cluster",
        ShardCount = 3,
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        Region = "us-central1",
        ReplicaCount = 1,
        NodeType = "REDIS_SHARED_CORE_NANO",
        TransitEncryptionMode = "TRANSIT_ENCRYPTION_MODE_DISABLED",
        AuthorizationMode = "AUTH_MODE_DISABLED",
        RedisConfigs = 
        {
            { "maxmemory-policy", "volatile-ttl" },
        },
        DeletionProtectionEnabled = true,
        ZoneDistributionConfig = new Gcp.Redis.Inputs.ClusterZoneDistributionConfigArgs
        {
            Mode = "MULTI_ZONE",
        },
        MaintenancePolicy = new Gcp.Redis.Inputs.ClusterMaintenancePolicyArgs
        {
            WeeklyMaintenanceWindows = new[]
            {
                new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs
                {
                    Day = "MONDAY",
                    StartTime = new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs
                    {
                        Hours = 1,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            @default,
        },
    });

});
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.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicy;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicyArgs;
import com.pulumi.gcp.networkconnectivity.inputs.ServiceConnectionPolicyPscConfigArgs;
import com.pulumi.gcp.redis.Cluster;
import com.pulumi.gcp.redis.ClusterArgs;
import com.pulumi.gcp.redis.inputs.ClusterPscConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterZoneDistributionConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterMaintenancePolicyArgs;
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 consumerNet = new Network("consumerNet", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var consumerSubnet = new Subnetwork("consumerSubnet", SubnetworkArgs.builder()
            .name("my-subnet")
            .ipCidrRange("10.0.0.248/29")
            .region("us-central1")
            .network(consumerNet.id())
            .build());

        var default_ = new ServiceConnectionPolicy("default", ServiceConnectionPolicyArgs.builder()
            .name("my-policy")
            .location("us-central1")
            .serviceClass("gcp-memorystore-redis")
            .description("my basic service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(consumerSubnet.id())
                .build())
            .build());

        var cluster_ha = new Cluster("cluster-ha", ClusterArgs.builder()
            .name("ha-cluster")
            .shardCount(3)
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .region("us-central1")
            .replicaCount(1)
            .nodeType("REDIS_SHARED_CORE_NANO")
            .transitEncryptionMode("TRANSIT_ENCRYPTION_MODE_DISABLED")
            .authorizationMode("AUTH_MODE_DISABLED")
            .redisConfigs(Map.of("maxmemory-policy", "volatile-ttl"))
            .deletionProtectionEnabled(true)
            .zoneDistributionConfig(ClusterZoneDistributionConfigArgs.builder()
                .mode("MULTI_ZONE")
                .build())
            .maintenancePolicy(ClusterMaintenancePolicyArgs.builder()
                .weeklyMaintenanceWindows(ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs.builder()
                    .day("MONDAY")
                    .startTime(ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs.builder()
                        .hours(1)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(default_)
                .build());

    }
}
resources:
  cluster-ha:
    type: gcp:redis:Cluster
    properties:
      name: ha-cluster
      shardCount: 3
      pscConfigs:
        - network: ${consumerNet.id}
      region: us-central1
      replicaCount: 1
      nodeType: REDIS_SHARED_CORE_NANO
      transitEncryptionMode: TRANSIT_ENCRYPTION_MODE_DISABLED
      authorizationMode: AUTH_MODE_DISABLED
      redisConfigs:
        maxmemory-policy: volatile-ttl
      deletionProtectionEnabled: true
      zoneDistributionConfig:
        mode: MULTI_ZONE
      maintenancePolicy:
        weeklyMaintenanceWindows:
          - day: MONDAY
            startTime:
              hours: 1
              minutes: 0
              seconds: 0
              nanos: 0
    options:
      dependsOn:
        - ${default}
  default:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    properties:
      name: my-policy
      location: us-central1
      serviceClass: gcp-memorystore-redis
      description: my basic service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${consumerSubnet.id}
  consumerSubnet:
    type: gcp:compute:Subnetwork
    name: consumer_subnet
    properties:
      name: my-subnet
      ipCidrRange: 10.0.0.248/29
      region: us-central1
      network: ${consumerNet.id}
  consumerNet:
    type: gcp:compute:Network
    name: consumer_net
    properties:
      name: my-network
      autoCreateSubnetworks: false

The cluster spreads data across shardCount shards, each with replicaCount replicas. The zoneDistributionConfig with mode MULTI_ZONE places shards and replicas across zones automatically. The pscConfigs property connects the cluster to your VPC via Private Service Connect. The nodeType determines compute and memory capacity per node.

Pin a cluster to a single availability zone

Some workloads prioritize low latency over zone-level redundancy and benefit from keeping all cluster nodes in the same zone.

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

const consumerNet = new gcp.compute.Network("consumer_net", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const consumerSubnet = new gcp.compute.Subnetwork("consumer_subnet", {
    name: "my-subnet",
    ipCidrRange: "10.0.0.248/29",
    region: "us-central1",
    network: consumerNet.id,
});
const _default = new gcp.networkconnectivity.ServiceConnectionPolicy("default", {
    name: "my-policy",
    location: "us-central1",
    serviceClass: "gcp-memorystore-redis",
    description: "my basic service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [consumerSubnet.id],
    },
});
const cluster_ha_single_zone = new gcp.redis.Cluster("cluster-ha-single-zone", {
    name: "ha-cluster-single-zone",
    shardCount: 3,
    pscConfigs: [{
        network: consumerNet.id,
    }],
    region: "us-central1",
    zoneDistributionConfig: {
        mode: "SINGLE_ZONE",
        zone: "us-central1-f",
    },
    maintenancePolicy: {
        weeklyMaintenanceWindows: [{
            day: "MONDAY",
            startTime: {
                hours: 1,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            },
        }],
    },
    deletionProtectionEnabled: true,
}, {
    dependsOn: [_default],
});
import pulumi
import pulumi_gcp as gcp

consumer_net = gcp.compute.Network("consumer_net",
    name="my-network",
    auto_create_subnetworks=False)
consumer_subnet = gcp.compute.Subnetwork("consumer_subnet",
    name="my-subnet",
    ip_cidr_range="10.0.0.248/29",
    region="us-central1",
    network=consumer_net.id)
default = gcp.networkconnectivity.ServiceConnectionPolicy("default",
    name="my-policy",
    location="us-central1",
    service_class="gcp-memorystore-redis",
    description="my basic service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [consumer_subnet.id],
    })
cluster_ha_single_zone = gcp.redis.Cluster("cluster-ha-single-zone",
    name="ha-cluster-single-zone",
    shard_count=3,
    psc_configs=[{
        "network": consumer_net.id,
    }],
    region="us-central1",
    zone_distribution_config={
        "mode": "SINGLE_ZONE",
        "zone": "us-central1-f",
    },
    maintenance_policy={
        "weekly_maintenance_windows": [{
            "day": "MONDAY",
            "start_time": {
                "hours": 1,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            },
        }],
    },
    deletion_protection_enabled=True,
    opts = pulumi.ResourceOptions(depends_on=[default]))
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		consumerNet, err := compute.NewNetwork(ctx, "consumer_net", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		consumerSubnet, err := compute.NewSubnetwork(ctx, "consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("my-subnet"),
			IpCidrRange: pulumi.String("10.0.0.248/29"),
			Region:      pulumi.String("us-central1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		_default, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "default", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("my-policy"),
			Location:     pulumi.String("us-central1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("my basic service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					consumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = redis.NewCluster(ctx, "cluster-ha-single-zone", &redis.ClusterArgs{
			Name:       pulumi.String("ha-cluster-single-zone"),
			ShardCount: pulumi.Int(3),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			Region: pulumi.String("us-central1"),
			ZoneDistributionConfig: &redis.ClusterZoneDistributionConfigArgs{
				Mode: pulumi.String("SINGLE_ZONE"),
				Zone: pulumi.String("us-central1-f"),
			},
			MaintenancePolicy: &redis.ClusterMaintenancePolicyArgs{
				WeeklyMaintenanceWindows: redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArray{
					&redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs{
						Day: pulumi.String("MONDAY"),
						StartTime: &redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs{
							Hours:   pulumi.Int(1),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
			},
			DeletionProtectionEnabled: pulumi.Bool(true),
		}, pulumi.DependsOn([]pulumi.Resource{
			_default,
		}))
		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 consumerNet = new Gcp.Compute.Network("consumer_net", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var consumerSubnet = new Gcp.Compute.Subnetwork("consumer_subnet", new()
    {
        Name = "my-subnet",
        IpCidrRange = "10.0.0.248/29",
        Region = "us-central1",
        Network = consumerNet.Id,
    });

    var @default = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("default", new()
    {
        Name = "my-policy",
        Location = "us-central1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "my basic service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                consumerSubnet.Id,
            },
        },
    });

    var cluster_ha_single_zone = new Gcp.Redis.Cluster("cluster-ha-single-zone", new()
    {
        Name = "ha-cluster-single-zone",
        ShardCount = 3,
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        Region = "us-central1",
        ZoneDistributionConfig = new Gcp.Redis.Inputs.ClusterZoneDistributionConfigArgs
        {
            Mode = "SINGLE_ZONE",
            Zone = "us-central1-f",
        },
        MaintenancePolicy = new Gcp.Redis.Inputs.ClusterMaintenancePolicyArgs
        {
            WeeklyMaintenanceWindows = new[]
            {
                new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs
                {
                    Day = "MONDAY",
                    StartTime = new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs
                    {
                        Hours = 1,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
        },
        DeletionProtectionEnabled = true,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            @default,
        },
    });

});
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.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicy;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicyArgs;
import com.pulumi.gcp.networkconnectivity.inputs.ServiceConnectionPolicyPscConfigArgs;
import com.pulumi.gcp.redis.Cluster;
import com.pulumi.gcp.redis.ClusterArgs;
import com.pulumi.gcp.redis.inputs.ClusterPscConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterZoneDistributionConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterMaintenancePolicyArgs;
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 consumerNet = new Network("consumerNet", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var consumerSubnet = new Subnetwork("consumerSubnet", SubnetworkArgs.builder()
            .name("my-subnet")
            .ipCidrRange("10.0.0.248/29")
            .region("us-central1")
            .network(consumerNet.id())
            .build());

        var default_ = new ServiceConnectionPolicy("default", ServiceConnectionPolicyArgs.builder()
            .name("my-policy")
            .location("us-central1")
            .serviceClass("gcp-memorystore-redis")
            .description("my basic service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(consumerSubnet.id())
                .build())
            .build());

        var cluster_ha_single_zone = new Cluster("cluster-ha-single-zone", ClusterArgs.builder()
            .name("ha-cluster-single-zone")
            .shardCount(3)
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .region("us-central1")
            .zoneDistributionConfig(ClusterZoneDistributionConfigArgs.builder()
                .mode("SINGLE_ZONE")
                .zone("us-central1-f")
                .build())
            .maintenancePolicy(ClusterMaintenancePolicyArgs.builder()
                .weeklyMaintenanceWindows(ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs.builder()
                    .day("MONDAY")
                    .startTime(ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs.builder()
                        .hours(1)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .build())
            .deletionProtectionEnabled(true)
            .build(), CustomResourceOptions.builder()
                .dependsOn(default_)
                .build());

    }
}
resources:
  cluster-ha-single-zone:
    type: gcp:redis:Cluster
    properties:
      name: ha-cluster-single-zone
      shardCount: 3
      pscConfigs:
        - network: ${consumerNet.id}
      region: us-central1
      zoneDistributionConfig:
        mode: SINGLE_ZONE
        zone: us-central1-f
      maintenancePolicy:
        weeklyMaintenanceWindows:
          - day: MONDAY
            startTime:
              hours: 1
              minutes: 0
              seconds: 0
              nanos: 0
      deletionProtectionEnabled: true
    options:
      dependsOn:
        - ${default}
  default:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    properties:
      name: my-policy
      location: us-central1
      serviceClass: gcp-memorystore-redis
      description: my basic service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${consumerSubnet.id}
  consumerSubnet:
    type: gcp:compute:Subnetwork
    name: consumer_subnet
    properties:
      name: my-subnet
      ipCidrRange: 10.0.0.248/29
      region: us-central1
      network: ${consumerNet.id}
  consumerNet:
    type: gcp:compute:Network
    name: consumer_net
    properties:
      name: my-network
      autoCreateSubnetworks: false

Setting zoneDistributionConfig.mode to SINGLE_ZONE and specifying a zone pins all shards and replicas to that zone. This reduces cross-zone network latency but eliminates automatic failover during zone outages. Use this for development environments or latency-critical workloads that have other redundancy strategies.

Configure cross-region replication with primary and secondary

Applications requiring disaster recovery or global read distribution deploy clusters across regions with automatic replication from primary to secondary.

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

const consumerNet = new gcp.compute.Network("consumer_net", {
    name: "mynetwork",
    autoCreateSubnetworks: false,
});
const primaryClusterConsumerSubnet = new gcp.compute.Subnetwork("primary_cluster_consumer_subnet", {
    name: "mysubnet-primary-cluster",
    ipCidrRange: "10.0.1.0/29",
    region: "us-east1",
    network: consumerNet.id,
});
const primaryClusterRegionScp = new gcp.networkconnectivity.ServiceConnectionPolicy("primary_cluster_region_scp", {
    name: "mypolicy-primary-cluster",
    location: "us-east1",
    serviceClass: "gcp-memorystore-redis",
    description: "Primary cluster service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [primaryClusterConsumerSubnet.id],
    },
});
// Primary cluster
const primaryCluster = new gcp.redis.Cluster("primary_cluster", {
    name: "my-primary-cluster",
    region: "us-east1",
    pscConfigs: [{
        network: consumerNet.id,
    }],
    authorizationMode: "AUTH_MODE_DISABLED",
    transitEncryptionMode: "TRANSIT_ENCRYPTION_MODE_DISABLED",
    shardCount: 3,
    redisConfigs: {
        "maxmemory-policy": "volatile-ttl",
    },
    nodeType: "REDIS_HIGHMEM_MEDIUM",
    persistenceConfig: {
        mode: "RDB",
        rdbConfig: {
            rdbSnapshotPeriod: "ONE_HOUR",
            rdbSnapshotStartTime: "2024-10-02T15:01:23Z",
        },
    },
    zoneDistributionConfig: {
        mode: "MULTI_ZONE",
    },
    replicaCount: 1,
    maintenancePolicy: {
        weeklyMaintenanceWindows: [{
            day: "MONDAY",
            startTime: {
                hours: 1,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            },
        }],
    },
    deletionProtectionEnabled: true,
}, {
    dependsOn: [primaryClusterRegionScp],
});
const secondaryClusterConsumerSubnet = new gcp.compute.Subnetwork("secondary_cluster_consumer_subnet", {
    name: "mysubnet-secondary-cluster",
    ipCidrRange: "10.0.2.0/29",
    region: "europe-west1",
    network: consumerNet.id,
});
const secondaryClusterRegionScp = new gcp.networkconnectivity.ServiceConnectionPolicy("secondary_cluster_region_scp", {
    name: "mypolicy-secondary-cluster",
    location: "europe-west1",
    serviceClass: "gcp-memorystore-redis",
    description: "Secondary cluster service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [secondaryClusterConsumerSubnet.id],
    },
});
// Secondary cluster
const secondaryCluster = new gcp.redis.Cluster("secondary_cluster", {
    name: "my-secondary-cluster",
    region: "europe-west1",
    pscConfigs: [{
        network: consumerNet.id,
    }],
    authorizationMode: "AUTH_MODE_DISABLED",
    transitEncryptionMode: "TRANSIT_ENCRYPTION_MODE_DISABLED",
    shardCount: 3,
    redisConfigs: {
        "maxmemory-policy": "volatile-ttl",
    },
    nodeType: "REDIS_HIGHMEM_MEDIUM",
    persistenceConfig: {
        mode: "RDB",
        rdbConfig: {
            rdbSnapshotPeriod: "ONE_HOUR",
            rdbSnapshotStartTime: "2024-10-02T15:01:23Z",
        },
    },
    zoneDistributionConfig: {
        mode: "MULTI_ZONE",
    },
    replicaCount: 2,
    maintenancePolicy: {
        weeklyMaintenanceWindows: [{
            day: "WEDNESDAY",
            startTime: {
                hours: 1,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            },
        }],
    },
    deletionProtectionEnabled: true,
    crossClusterReplicationConfig: {
        clusterRole: "SECONDARY",
        primaryCluster: {
            cluster: primaryCluster.id,
        },
    },
}, {
    dependsOn: [secondaryClusterRegionScp],
});
import pulumi
import pulumi_gcp as gcp

consumer_net = gcp.compute.Network("consumer_net",
    name="mynetwork",
    auto_create_subnetworks=False)
primary_cluster_consumer_subnet = gcp.compute.Subnetwork("primary_cluster_consumer_subnet",
    name="mysubnet-primary-cluster",
    ip_cidr_range="10.0.1.0/29",
    region="us-east1",
    network=consumer_net.id)
primary_cluster_region_scp = gcp.networkconnectivity.ServiceConnectionPolicy("primary_cluster_region_scp",
    name="mypolicy-primary-cluster",
    location="us-east1",
    service_class="gcp-memorystore-redis",
    description="Primary cluster service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [primary_cluster_consumer_subnet.id],
    })
# Primary cluster
primary_cluster = gcp.redis.Cluster("primary_cluster",
    name="my-primary-cluster",
    region="us-east1",
    psc_configs=[{
        "network": consumer_net.id,
    }],
    authorization_mode="AUTH_MODE_DISABLED",
    transit_encryption_mode="TRANSIT_ENCRYPTION_MODE_DISABLED",
    shard_count=3,
    redis_configs={
        "maxmemory-policy": "volatile-ttl",
    },
    node_type="REDIS_HIGHMEM_MEDIUM",
    persistence_config={
        "mode": "RDB",
        "rdb_config": {
            "rdb_snapshot_period": "ONE_HOUR",
            "rdb_snapshot_start_time": "2024-10-02T15:01:23Z",
        },
    },
    zone_distribution_config={
        "mode": "MULTI_ZONE",
    },
    replica_count=1,
    maintenance_policy={
        "weekly_maintenance_windows": [{
            "day": "MONDAY",
            "start_time": {
                "hours": 1,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            },
        }],
    },
    deletion_protection_enabled=True,
    opts = pulumi.ResourceOptions(depends_on=[primary_cluster_region_scp]))
secondary_cluster_consumer_subnet = gcp.compute.Subnetwork("secondary_cluster_consumer_subnet",
    name="mysubnet-secondary-cluster",
    ip_cidr_range="10.0.2.0/29",
    region="europe-west1",
    network=consumer_net.id)
secondary_cluster_region_scp = gcp.networkconnectivity.ServiceConnectionPolicy("secondary_cluster_region_scp",
    name="mypolicy-secondary-cluster",
    location="europe-west1",
    service_class="gcp-memorystore-redis",
    description="Secondary cluster service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [secondary_cluster_consumer_subnet.id],
    })
# Secondary cluster
secondary_cluster = gcp.redis.Cluster("secondary_cluster",
    name="my-secondary-cluster",
    region="europe-west1",
    psc_configs=[{
        "network": consumer_net.id,
    }],
    authorization_mode="AUTH_MODE_DISABLED",
    transit_encryption_mode="TRANSIT_ENCRYPTION_MODE_DISABLED",
    shard_count=3,
    redis_configs={
        "maxmemory-policy": "volatile-ttl",
    },
    node_type="REDIS_HIGHMEM_MEDIUM",
    persistence_config={
        "mode": "RDB",
        "rdb_config": {
            "rdb_snapshot_period": "ONE_HOUR",
            "rdb_snapshot_start_time": "2024-10-02T15:01:23Z",
        },
    },
    zone_distribution_config={
        "mode": "MULTI_ZONE",
    },
    replica_count=2,
    maintenance_policy={
        "weekly_maintenance_windows": [{
            "day": "WEDNESDAY",
            "start_time": {
                "hours": 1,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            },
        }],
    },
    deletion_protection_enabled=True,
    cross_cluster_replication_config={
        "cluster_role": "SECONDARY",
        "primary_cluster": {
            "cluster": primary_cluster.id,
        },
    },
    opts = pulumi.ResourceOptions(depends_on=[secondary_cluster_region_scp]))
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		consumerNet, err := compute.NewNetwork(ctx, "consumer_net", &compute.NetworkArgs{
			Name:                  pulumi.String("mynetwork"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		primaryClusterConsumerSubnet, err := compute.NewSubnetwork(ctx, "primary_cluster_consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("mysubnet-primary-cluster"),
			IpCidrRange: pulumi.String("10.0.1.0/29"),
			Region:      pulumi.String("us-east1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		primaryClusterRegionScp, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "primary_cluster_region_scp", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("mypolicy-primary-cluster"),
			Location:     pulumi.String("us-east1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("Primary cluster service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					primaryClusterConsumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		// Primary cluster
		primaryCluster, err := redis.NewCluster(ctx, "primary_cluster", &redis.ClusterArgs{
			Name:   pulumi.String("my-primary-cluster"),
			Region: pulumi.String("us-east1"),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			AuthorizationMode:     pulumi.String("AUTH_MODE_DISABLED"),
			TransitEncryptionMode: pulumi.String("TRANSIT_ENCRYPTION_MODE_DISABLED"),
			ShardCount:            pulumi.Int(3),
			RedisConfigs: pulumi.StringMap{
				"maxmemory-policy": pulumi.String("volatile-ttl"),
			},
			NodeType: pulumi.String("REDIS_HIGHMEM_MEDIUM"),
			PersistenceConfig: &redis.ClusterPersistenceConfigArgs{
				Mode: pulumi.String("RDB"),
				RdbConfig: &redis.ClusterPersistenceConfigRdbConfigArgs{
					RdbSnapshotPeriod:    pulumi.String("ONE_HOUR"),
					RdbSnapshotStartTime: pulumi.String("2024-10-02T15:01:23Z"),
				},
			},
			ZoneDistributionConfig: &redis.ClusterZoneDistributionConfigArgs{
				Mode: pulumi.String("MULTI_ZONE"),
			},
			ReplicaCount: pulumi.Int(1),
			MaintenancePolicy: &redis.ClusterMaintenancePolicyArgs{
				WeeklyMaintenanceWindows: redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArray{
					&redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs{
						Day: pulumi.String("MONDAY"),
						StartTime: &redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs{
							Hours:   pulumi.Int(1),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
			},
			DeletionProtectionEnabled: pulumi.Bool(true),
		}, pulumi.DependsOn([]pulumi.Resource{
			primaryClusterRegionScp,
		}))
		if err != nil {
			return err
		}
		secondaryClusterConsumerSubnet, err := compute.NewSubnetwork(ctx, "secondary_cluster_consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("mysubnet-secondary-cluster"),
			IpCidrRange: pulumi.String("10.0.2.0/29"),
			Region:      pulumi.String("europe-west1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		secondaryClusterRegionScp, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "secondary_cluster_region_scp", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("mypolicy-secondary-cluster"),
			Location:     pulumi.String("europe-west1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("Secondary cluster service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					secondaryClusterConsumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		// Secondary cluster
		_, err = redis.NewCluster(ctx, "secondary_cluster", &redis.ClusterArgs{
			Name:   pulumi.String("my-secondary-cluster"),
			Region: pulumi.String("europe-west1"),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			AuthorizationMode:     pulumi.String("AUTH_MODE_DISABLED"),
			TransitEncryptionMode: pulumi.String("TRANSIT_ENCRYPTION_MODE_DISABLED"),
			ShardCount:            pulumi.Int(3),
			RedisConfigs: pulumi.StringMap{
				"maxmemory-policy": pulumi.String("volatile-ttl"),
			},
			NodeType: pulumi.String("REDIS_HIGHMEM_MEDIUM"),
			PersistenceConfig: &redis.ClusterPersistenceConfigArgs{
				Mode: pulumi.String("RDB"),
				RdbConfig: &redis.ClusterPersistenceConfigRdbConfigArgs{
					RdbSnapshotPeriod:    pulumi.String("ONE_HOUR"),
					RdbSnapshotStartTime: pulumi.String("2024-10-02T15:01:23Z"),
				},
			},
			ZoneDistributionConfig: &redis.ClusterZoneDistributionConfigArgs{
				Mode: pulumi.String("MULTI_ZONE"),
			},
			ReplicaCount: pulumi.Int(2),
			MaintenancePolicy: &redis.ClusterMaintenancePolicyArgs{
				WeeklyMaintenanceWindows: redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArray{
					&redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs{
						Day: pulumi.String("WEDNESDAY"),
						StartTime: &redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs{
							Hours:   pulumi.Int(1),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
			},
			DeletionProtectionEnabled: pulumi.Bool(true),
			CrossClusterReplicationConfig: &redis.ClusterCrossClusterReplicationConfigArgs{
				ClusterRole: pulumi.String("SECONDARY"),
				PrimaryCluster: &redis.ClusterCrossClusterReplicationConfigPrimaryClusterArgs{
					Cluster: primaryCluster.ID(),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			secondaryClusterRegionScp,
		}))
		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 consumerNet = new Gcp.Compute.Network("consumer_net", new()
    {
        Name = "mynetwork",
        AutoCreateSubnetworks = false,
    });

    var primaryClusterConsumerSubnet = new Gcp.Compute.Subnetwork("primary_cluster_consumer_subnet", new()
    {
        Name = "mysubnet-primary-cluster",
        IpCidrRange = "10.0.1.0/29",
        Region = "us-east1",
        Network = consumerNet.Id,
    });

    var primaryClusterRegionScp = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("primary_cluster_region_scp", new()
    {
        Name = "mypolicy-primary-cluster",
        Location = "us-east1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "Primary cluster service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                primaryClusterConsumerSubnet.Id,
            },
        },
    });

    // Primary cluster
    var primaryCluster = new Gcp.Redis.Cluster("primary_cluster", new()
    {
        Name = "my-primary-cluster",
        Region = "us-east1",
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        AuthorizationMode = "AUTH_MODE_DISABLED",
        TransitEncryptionMode = "TRANSIT_ENCRYPTION_MODE_DISABLED",
        ShardCount = 3,
        RedisConfigs = 
        {
            { "maxmemory-policy", "volatile-ttl" },
        },
        NodeType = "REDIS_HIGHMEM_MEDIUM",
        PersistenceConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigArgs
        {
            Mode = "RDB",
            RdbConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigRdbConfigArgs
            {
                RdbSnapshotPeriod = "ONE_HOUR",
                RdbSnapshotStartTime = "2024-10-02T15:01:23Z",
            },
        },
        ZoneDistributionConfig = new Gcp.Redis.Inputs.ClusterZoneDistributionConfigArgs
        {
            Mode = "MULTI_ZONE",
        },
        ReplicaCount = 1,
        MaintenancePolicy = new Gcp.Redis.Inputs.ClusterMaintenancePolicyArgs
        {
            WeeklyMaintenanceWindows = new[]
            {
                new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs
                {
                    Day = "MONDAY",
                    StartTime = new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs
                    {
                        Hours = 1,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
        },
        DeletionProtectionEnabled = true,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            primaryClusterRegionScp,
        },
    });

    var secondaryClusterConsumerSubnet = new Gcp.Compute.Subnetwork("secondary_cluster_consumer_subnet", new()
    {
        Name = "mysubnet-secondary-cluster",
        IpCidrRange = "10.0.2.0/29",
        Region = "europe-west1",
        Network = consumerNet.Id,
    });

    var secondaryClusterRegionScp = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("secondary_cluster_region_scp", new()
    {
        Name = "mypolicy-secondary-cluster",
        Location = "europe-west1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "Secondary cluster service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                secondaryClusterConsumerSubnet.Id,
            },
        },
    });

    // Secondary cluster
    var secondaryCluster = new Gcp.Redis.Cluster("secondary_cluster", new()
    {
        Name = "my-secondary-cluster",
        Region = "europe-west1",
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        AuthorizationMode = "AUTH_MODE_DISABLED",
        TransitEncryptionMode = "TRANSIT_ENCRYPTION_MODE_DISABLED",
        ShardCount = 3,
        RedisConfigs = 
        {
            { "maxmemory-policy", "volatile-ttl" },
        },
        NodeType = "REDIS_HIGHMEM_MEDIUM",
        PersistenceConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigArgs
        {
            Mode = "RDB",
            RdbConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigRdbConfigArgs
            {
                RdbSnapshotPeriod = "ONE_HOUR",
                RdbSnapshotStartTime = "2024-10-02T15:01:23Z",
            },
        },
        ZoneDistributionConfig = new Gcp.Redis.Inputs.ClusterZoneDistributionConfigArgs
        {
            Mode = "MULTI_ZONE",
        },
        ReplicaCount = 2,
        MaintenancePolicy = new Gcp.Redis.Inputs.ClusterMaintenancePolicyArgs
        {
            WeeklyMaintenanceWindows = new[]
            {
                new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs
                {
                    Day = "WEDNESDAY",
                    StartTime = new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs
                    {
                        Hours = 1,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
        },
        DeletionProtectionEnabled = true,
        CrossClusterReplicationConfig = new Gcp.Redis.Inputs.ClusterCrossClusterReplicationConfigArgs
        {
            ClusterRole = "SECONDARY",
            PrimaryCluster = new Gcp.Redis.Inputs.ClusterCrossClusterReplicationConfigPrimaryClusterArgs
            {
                Cluster = primaryCluster.Id,
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            secondaryClusterRegionScp,
        },
    });

});
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.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicy;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicyArgs;
import com.pulumi.gcp.networkconnectivity.inputs.ServiceConnectionPolicyPscConfigArgs;
import com.pulumi.gcp.redis.Cluster;
import com.pulumi.gcp.redis.ClusterArgs;
import com.pulumi.gcp.redis.inputs.ClusterPscConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterPersistenceConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterPersistenceConfigRdbConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterZoneDistributionConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterMaintenancePolicyArgs;
import com.pulumi.gcp.redis.inputs.ClusterCrossClusterReplicationConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterCrossClusterReplicationConfigPrimaryClusterArgs;
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 consumerNet = new Network("consumerNet", NetworkArgs.builder()
            .name("mynetwork")
            .autoCreateSubnetworks(false)
            .build());

        var primaryClusterConsumerSubnet = new Subnetwork("primaryClusterConsumerSubnet", SubnetworkArgs.builder()
            .name("mysubnet-primary-cluster")
            .ipCidrRange("10.0.1.0/29")
            .region("us-east1")
            .network(consumerNet.id())
            .build());

        var primaryClusterRegionScp = new ServiceConnectionPolicy("primaryClusterRegionScp", ServiceConnectionPolicyArgs.builder()
            .name("mypolicy-primary-cluster")
            .location("us-east1")
            .serviceClass("gcp-memorystore-redis")
            .description("Primary cluster service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(primaryClusterConsumerSubnet.id())
                .build())
            .build());

        // Primary cluster
        var primaryCluster = new Cluster("primaryCluster", ClusterArgs.builder()
            .name("my-primary-cluster")
            .region("us-east1")
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .authorizationMode("AUTH_MODE_DISABLED")
            .transitEncryptionMode("TRANSIT_ENCRYPTION_MODE_DISABLED")
            .shardCount(3)
            .redisConfigs(Map.of("maxmemory-policy", "volatile-ttl"))
            .nodeType("REDIS_HIGHMEM_MEDIUM")
            .persistenceConfig(ClusterPersistenceConfigArgs.builder()
                .mode("RDB")
                .rdbConfig(ClusterPersistenceConfigRdbConfigArgs.builder()
                    .rdbSnapshotPeriod("ONE_HOUR")
                    .rdbSnapshotStartTime("2024-10-02T15:01:23Z")
                    .build())
                .build())
            .zoneDistributionConfig(ClusterZoneDistributionConfigArgs.builder()
                .mode("MULTI_ZONE")
                .build())
            .replicaCount(1)
            .maintenancePolicy(ClusterMaintenancePolicyArgs.builder()
                .weeklyMaintenanceWindows(ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs.builder()
                    .day("MONDAY")
                    .startTime(ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs.builder()
                        .hours(1)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .build())
            .deletionProtectionEnabled(true)
            .build(), CustomResourceOptions.builder()
                .dependsOn(primaryClusterRegionScp)
                .build());

        var secondaryClusterConsumerSubnet = new Subnetwork("secondaryClusterConsumerSubnet", SubnetworkArgs.builder()
            .name("mysubnet-secondary-cluster")
            .ipCidrRange("10.0.2.0/29")
            .region("europe-west1")
            .network(consumerNet.id())
            .build());

        var secondaryClusterRegionScp = new ServiceConnectionPolicy("secondaryClusterRegionScp", ServiceConnectionPolicyArgs.builder()
            .name("mypolicy-secondary-cluster")
            .location("europe-west1")
            .serviceClass("gcp-memorystore-redis")
            .description("Secondary cluster service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(secondaryClusterConsumerSubnet.id())
                .build())
            .build());

        // Secondary cluster
        var secondaryCluster = new Cluster("secondaryCluster", ClusterArgs.builder()
            .name("my-secondary-cluster")
            .region("europe-west1")
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .authorizationMode("AUTH_MODE_DISABLED")
            .transitEncryptionMode("TRANSIT_ENCRYPTION_MODE_DISABLED")
            .shardCount(3)
            .redisConfigs(Map.of("maxmemory-policy", "volatile-ttl"))
            .nodeType("REDIS_HIGHMEM_MEDIUM")
            .persistenceConfig(ClusterPersistenceConfigArgs.builder()
                .mode("RDB")
                .rdbConfig(ClusterPersistenceConfigRdbConfigArgs.builder()
                    .rdbSnapshotPeriod("ONE_HOUR")
                    .rdbSnapshotStartTime("2024-10-02T15:01:23Z")
                    .build())
                .build())
            .zoneDistributionConfig(ClusterZoneDistributionConfigArgs.builder()
                .mode("MULTI_ZONE")
                .build())
            .replicaCount(2)
            .maintenancePolicy(ClusterMaintenancePolicyArgs.builder()
                .weeklyMaintenanceWindows(ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs.builder()
                    .day("WEDNESDAY")
                    .startTime(ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs.builder()
                        .hours(1)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .build())
            .deletionProtectionEnabled(true)
            .crossClusterReplicationConfig(ClusterCrossClusterReplicationConfigArgs.builder()
                .clusterRole("SECONDARY")
                .primaryCluster(ClusterCrossClusterReplicationConfigPrimaryClusterArgs.builder()
                    .cluster(primaryCluster.id())
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(secondaryClusterRegionScp)
                .build());

    }
}
resources:
  # Primary cluster
  primaryCluster:
    type: gcp:redis:Cluster
    name: primary_cluster
    properties:
      name: my-primary-cluster
      region: us-east1
      pscConfigs:
        - network: ${consumerNet.id}
      authorizationMode: AUTH_MODE_DISABLED
      transitEncryptionMode: TRANSIT_ENCRYPTION_MODE_DISABLED
      shardCount: 3
      redisConfigs:
        maxmemory-policy: volatile-ttl
      nodeType: REDIS_HIGHMEM_MEDIUM
      persistenceConfig:
        mode: RDB
        rdbConfig:
          rdbSnapshotPeriod: ONE_HOUR
          rdbSnapshotStartTime: 2024-10-02T15:01:23Z
      zoneDistributionConfig:
        mode: MULTI_ZONE
      replicaCount: 1
      maintenancePolicy:
        weeklyMaintenanceWindows:
          - day: MONDAY
            startTime:
              hours: 1
              minutes: 0
              seconds: 0
              nanos: 0
      deletionProtectionEnabled: true
    options:
      dependsOn:
        - ${primaryClusterRegionScp}
  # Secondary cluster
  secondaryCluster:
    type: gcp:redis:Cluster
    name: secondary_cluster
    properties:
      name: my-secondary-cluster
      region: europe-west1
      pscConfigs:
        - network: ${consumerNet.id}
      authorizationMode: AUTH_MODE_DISABLED
      transitEncryptionMode: TRANSIT_ENCRYPTION_MODE_DISABLED
      shardCount: 3
      redisConfigs:
        maxmemory-policy: volatile-ttl
      nodeType: REDIS_HIGHMEM_MEDIUM
      persistenceConfig:
        mode: RDB
        rdbConfig:
          rdbSnapshotPeriod: ONE_HOUR
          rdbSnapshotStartTime: 2024-10-02T15:01:23Z
      zoneDistributionConfig:
        mode: MULTI_ZONE
      replicaCount: 2
      maintenancePolicy:
        weeklyMaintenanceWindows:
          - day: WEDNESDAY
            startTime:
              hours: 1
              minutes: 0
              seconds: 0
              nanos: 0
      deletionProtectionEnabled: true # Cross cluster replication config
      crossClusterReplicationConfig:
        clusterRole: SECONDARY
        primaryCluster:
          cluster: ${primaryCluster.id}
    options:
      dependsOn:
        - ${secondaryClusterRegionScp}
  primaryClusterRegionScp:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    name: primary_cluster_region_scp
    properties:
      name: mypolicy-primary-cluster
      location: us-east1
      serviceClass: gcp-memorystore-redis
      description: Primary cluster service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${primaryClusterConsumerSubnet.id}
  primaryClusterConsumerSubnet:
    type: gcp:compute:Subnetwork
    name: primary_cluster_consumer_subnet
    properties:
      name: mysubnet-primary-cluster
      ipCidrRange: 10.0.1.0/29
      region: us-east1
      network: ${consumerNet.id}
  secondaryClusterRegionScp:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    name: secondary_cluster_region_scp
    properties:
      name: mypolicy-secondary-cluster
      location: europe-west1
      serviceClass: gcp-memorystore-redis
      description: Secondary cluster service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${secondaryClusterConsumerSubnet.id}
  secondaryClusterConsumerSubnet:
    type: gcp:compute:Subnetwork
    name: secondary_cluster_consumer_subnet
    properties:
      name: mysubnet-secondary-cluster
      ipCidrRange: 10.0.2.0/29
      region: europe-west1
      network: ${consumerNet.id}
  consumerNet:
    type: gcp:compute:Network
    name: consumer_net
    properties:
      name: mynetwork
      autoCreateSubnetworks: false

The crossClusterReplicationConfig property establishes the replication relationship. The secondary cluster sets clusterRole to SECONDARY and references the primary cluster ID. Changes to the primary propagate automatically to secondaries. Each cluster requires its own VPC network and ServiceConnectionPolicy in its region. The documentation includes detailed procedures for switchover and detachment operations.

Enable RDB snapshots for point-in-time recovery

Clusters storing critical data enable RDB persistence to create periodic snapshots that can restore data after failures or accidental deletions.

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

const consumerNet = new gcp.compute.Network("consumer_net", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const consumerSubnet = new gcp.compute.Subnetwork("consumer_subnet", {
    name: "my-subnet",
    ipCidrRange: "10.0.0.248/29",
    region: "us-central1",
    network: consumerNet.id,
});
const _default = new gcp.networkconnectivity.ServiceConnectionPolicy("default", {
    name: "my-policy",
    location: "us-central1",
    serviceClass: "gcp-memorystore-redis",
    description: "my basic service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [consumerSubnet.id],
    },
});
const cluster_rdb = new gcp.redis.Cluster("cluster-rdb", {
    name: "rdb-cluster",
    shardCount: 3,
    pscConfigs: [{
        network: consumerNet.id,
    }],
    region: "us-central1",
    replicaCount: 0,
    nodeType: "REDIS_SHARED_CORE_NANO",
    transitEncryptionMode: "TRANSIT_ENCRYPTION_MODE_DISABLED",
    authorizationMode: "AUTH_MODE_DISABLED",
    redisConfigs: {
        "maxmemory-policy": "volatile-ttl",
    },
    deletionProtectionEnabled: true,
    zoneDistributionConfig: {
        mode: "MULTI_ZONE",
    },
    maintenancePolicy: {
        weeklyMaintenanceWindows: [{
            day: "MONDAY",
            startTime: {
                hours: 1,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            },
        }],
    },
    persistenceConfig: {
        mode: "RDB",
        rdbConfig: {
            rdbSnapshotPeriod: "ONE_HOUR",
            rdbSnapshotStartTime: "2024-10-02T15:01:23Z",
        },
    },
}, {
    dependsOn: [_default],
});
import pulumi
import pulumi_gcp as gcp

consumer_net = gcp.compute.Network("consumer_net",
    name="my-network",
    auto_create_subnetworks=False)
consumer_subnet = gcp.compute.Subnetwork("consumer_subnet",
    name="my-subnet",
    ip_cidr_range="10.0.0.248/29",
    region="us-central1",
    network=consumer_net.id)
default = gcp.networkconnectivity.ServiceConnectionPolicy("default",
    name="my-policy",
    location="us-central1",
    service_class="gcp-memorystore-redis",
    description="my basic service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [consumer_subnet.id],
    })
cluster_rdb = gcp.redis.Cluster("cluster-rdb",
    name="rdb-cluster",
    shard_count=3,
    psc_configs=[{
        "network": consumer_net.id,
    }],
    region="us-central1",
    replica_count=0,
    node_type="REDIS_SHARED_CORE_NANO",
    transit_encryption_mode="TRANSIT_ENCRYPTION_MODE_DISABLED",
    authorization_mode="AUTH_MODE_DISABLED",
    redis_configs={
        "maxmemory-policy": "volatile-ttl",
    },
    deletion_protection_enabled=True,
    zone_distribution_config={
        "mode": "MULTI_ZONE",
    },
    maintenance_policy={
        "weekly_maintenance_windows": [{
            "day": "MONDAY",
            "start_time": {
                "hours": 1,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            },
        }],
    },
    persistence_config={
        "mode": "RDB",
        "rdb_config": {
            "rdb_snapshot_period": "ONE_HOUR",
            "rdb_snapshot_start_time": "2024-10-02T15:01:23Z",
        },
    },
    opts = pulumi.ResourceOptions(depends_on=[default]))
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		consumerNet, err := compute.NewNetwork(ctx, "consumer_net", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		consumerSubnet, err := compute.NewSubnetwork(ctx, "consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("my-subnet"),
			IpCidrRange: pulumi.String("10.0.0.248/29"),
			Region:      pulumi.String("us-central1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		_default, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "default", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("my-policy"),
			Location:     pulumi.String("us-central1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("my basic service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					consumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = redis.NewCluster(ctx, "cluster-rdb", &redis.ClusterArgs{
			Name:       pulumi.String("rdb-cluster"),
			ShardCount: pulumi.Int(3),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			Region:                pulumi.String("us-central1"),
			ReplicaCount:          pulumi.Int(0),
			NodeType:              pulumi.String("REDIS_SHARED_CORE_NANO"),
			TransitEncryptionMode: pulumi.String("TRANSIT_ENCRYPTION_MODE_DISABLED"),
			AuthorizationMode:     pulumi.String("AUTH_MODE_DISABLED"),
			RedisConfigs: pulumi.StringMap{
				"maxmemory-policy": pulumi.String("volatile-ttl"),
			},
			DeletionProtectionEnabled: pulumi.Bool(true),
			ZoneDistributionConfig: &redis.ClusterZoneDistributionConfigArgs{
				Mode: pulumi.String("MULTI_ZONE"),
			},
			MaintenancePolicy: &redis.ClusterMaintenancePolicyArgs{
				WeeklyMaintenanceWindows: redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArray{
					&redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs{
						Day: pulumi.String("MONDAY"),
						StartTime: &redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs{
							Hours:   pulumi.Int(1),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
			},
			PersistenceConfig: &redis.ClusterPersistenceConfigArgs{
				Mode: pulumi.String("RDB"),
				RdbConfig: &redis.ClusterPersistenceConfigRdbConfigArgs{
					RdbSnapshotPeriod:    pulumi.String("ONE_HOUR"),
					RdbSnapshotStartTime: pulumi.String("2024-10-02T15:01:23Z"),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			_default,
		}))
		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 consumerNet = new Gcp.Compute.Network("consumer_net", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var consumerSubnet = new Gcp.Compute.Subnetwork("consumer_subnet", new()
    {
        Name = "my-subnet",
        IpCidrRange = "10.0.0.248/29",
        Region = "us-central1",
        Network = consumerNet.Id,
    });

    var @default = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("default", new()
    {
        Name = "my-policy",
        Location = "us-central1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "my basic service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                consumerSubnet.Id,
            },
        },
    });

    var cluster_rdb = new Gcp.Redis.Cluster("cluster-rdb", new()
    {
        Name = "rdb-cluster",
        ShardCount = 3,
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        Region = "us-central1",
        ReplicaCount = 0,
        NodeType = "REDIS_SHARED_CORE_NANO",
        TransitEncryptionMode = "TRANSIT_ENCRYPTION_MODE_DISABLED",
        AuthorizationMode = "AUTH_MODE_DISABLED",
        RedisConfigs = 
        {
            { "maxmemory-policy", "volatile-ttl" },
        },
        DeletionProtectionEnabled = true,
        ZoneDistributionConfig = new Gcp.Redis.Inputs.ClusterZoneDistributionConfigArgs
        {
            Mode = "MULTI_ZONE",
        },
        MaintenancePolicy = new Gcp.Redis.Inputs.ClusterMaintenancePolicyArgs
        {
            WeeklyMaintenanceWindows = new[]
            {
                new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs
                {
                    Day = "MONDAY",
                    StartTime = new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs
                    {
                        Hours = 1,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
        },
        PersistenceConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigArgs
        {
            Mode = "RDB",
            RdbConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigRdbConfigArgs
            {
                RdbSnapshotPeriod = "ONE_HOUR",
                RdbSnapshotStartTime = "2024-10-02T15:01:23Z",
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            @default,
        },
    });

});
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.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicy;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicyArgs;
import com.pulumi.gcp.networkconnectivity.inputs.ServiceConnectionPolicyPscConfigArgs;
import com.pulumi.gcp.redis.Cluster;
import com.pulumi.gcp.redis.ClusterArgs;
import com.pulumi.gcp.redis.inputs.ClusterPscConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterZoneDistributionConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterMaintenancePolicyArgs;
import com.pulumi.gcp.redis.inputs.ClusterPersistenceConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterPersistenceConfigRdbConfigArgs;
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 consumerNet = new Network("consumerNet", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var consumerSubnet = new Subnetwork("consumerSubnet", SubnetworkArgs.builder()
            .name("my-subnet")
            .ipCidrRange("10.0.0.248/29")
            .region("us-central1")
            .network(consumerNet.id())
            .build());

        var default_ = new ServiceConnectionPolicy("default", ServiceConnectionPolicyArgs.builder()
            .name("my-policy")
            .location("us-central1")
            .serviceClass("gcp-memorystore-redis")
            .description("my basic service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(consumerSubnet.id())
                .build())
            .build());

        var cluster_rdb = new Cluster("cluster-rdb", ClusterArgs.builder()
            .name("rdb-cluster")
            .shardCount(3)
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .region("us-central1")
            .replicaCount(0)
            .nodeType("REDIS_SHARED_CORE_NANO")
            .transitEncryptionMode("TRANSIT_ENCRYPTION_MODE_DISABLED")
            .authorizationMode("AUTH_MODE_DISABLED")
            .redisConfigs(Map.of("maxmemory-policy", "volatile-ttl"))
            .deletionProtectionEnabled(true)
            .zoneDistributionConfig(ClusterZoneDistributionConfigArgs.builder()
                .mode("MULTI_ZONE")
                .build())
            .maintenancePolicy(ClusterMaintenancePolicyArgs.builder()
                .weeklyMaintenanceWindows(ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs.builder()
                    .day("MONDAY")
                    .startTime(ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs.builder()
                        .hours(1)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .build())
            .persistenceConfig(ClusterPersistenceConfigArgs.builder()
                .mode("RDB")
                .rdbConfig(ClusterPersistenceConfigRdbConfigArgs.builder()
                    .rdbSnapshotPeriod("ONE_HOUR")
                    .rdbSnapshotStartTime("2024-10-02T15:01:23Z")
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(default_)
                .build());

    }
}
resources:
  cluster-rdb:
    type: gcp:redis:Cluster
    properties:
      name: rdb-cluster
      shardCount: 3
      pscConfigs:
        - network: ${consumerNet.id}
      region: us-central1
      replicaCount: 0
      nodeType: REDIS_SHARED_CORE_NANO
      transitEncryptionMode: TRANSIT_ENCRYPTION_MODE_DISABLED
      authorizationMode: AUTH_MODE_DISABLED
      redisConfigs:
        maxmemory-policy: volatile-ttl
      deletionProtectionEnabled: true
      zoneDistributionConfig:
        mode: MULTI_ZONE
      maintenancePolicy:
        weeklyMaintenanceWindows:
          - day: MONDAY
            startTime:
              hours: 1
              minutes: 0
              seconds: 0
              nanos: 0
      persistenceConfig:
        mode: RDB
        rdbConfig:
          rdbSnapshotPeriod: ONE_HOUR
          rdbSnapshotStartTime: 2024-10-02T15:01:23Z
    options:
      dependsOn:
        - ${default}
  default:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    properties:
      name: my-policy
      location: us-central1
      serviceClass: gcp-memorystore-redis
      description: my basic service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${consumerSubnet.id}
  consumerSubnet:
    type: gcp:compute:Subnetwork
    name: consumer_subnet
    properties:
      name: my-subnet
      ipCidrRange: 10.0.0.248/29
      region: us-central1
      network: ${consumerNet.id}
  consumerNet:
    type: gcp:compute:Network
    name: consumer_net
    properties:
      name: my-network
      autoCreateSubnetworks: false

The persistenceConfig property with mode RDB enables snapshot-based persistence. The rdbSnapshotPeriod controls how frequently snapshots occur (ONE_HOUR, SIX_HOURS, TWELVE_HOURS, or TWENTY_FOUR_HOURS). The rdbSnapshotStartTime sets when the first snapshot begins. RDB provides good durability with minimal performance impact but may lose writes between snapshots.

Enable AOF logging for maximum durability

Workloads that cannot tolerate any data loss use AOF persistence to log every write operation, providing stronger durability guarantees than RDB snapshots.

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

const consumerNet = new gcp.compute.Network("consumer_net", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const consumerSubnet = new gcp.compute.Subnetwork("consumer_subnet", {
    name: "my-subnet",
    ipCidrRange: "10.0.0.248/29",
    region: "us-central1",
    network: consumerNet.id,
});
const _default = new gcp.networkconnectivity.ServiceConnectionPolicy("default", {
    name: "my-policy",
    location: "us-central1",
    serviceClass: "gcp-memorystore-redis",
    description: "my basic service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [consumerSubnet.id],
    },
});
const cluster_aof = new gcp.redis.Cluster("cluster-aof", {
    name: "aof-cluster",
    shardCount: 3,
    pscConfigs: [{
        network: consumerNet.id,
    }],
    region: "us-central1",
    replicaCount: 0,
    nodeType: "REDIS_SHARED_CORE_NANO",
    transitEncryptionMode: "TRANSIT_ENCRYPTION_MODE_DISABLED",
    authorizationMode: "AUTH_MODE_DISABLED",
    redisConfigs: {
        "maxmemory-policy": "volatile-ttl",
    },
    deletionProtectionEnabled: true,
    zoneDistributionConfig: {
        mode: "MULTI_ZONE",
    },
    maintenancePolicy: {
        weeklyMaintenanceWindows: [{
            day: "MONDAY",
            startTime: {
                hours: 1,
                minutes: 0,
                seconds: 0,
                nanos: 0,
            },
        }],
    },
    persistenceConfig: {
        mode: "AOF",
        aofConfig: {
            appendFsync: "EVERYSEC",
        },
    },
}, {
    dependsOn: [_default],
});
import pulumi
import pulumi_gcp as gcp

consumer_net = gcp.compute.Network("consumer_net",
    name="my-network",
    auto_create_subnetworks=False)
consumer_subnet = gcp.compute.Subnetwork("consumer_subnet",
    name="my-subnet",
    ip_cidr_range="10.0.0.248/29",
    region="us-central1",
    network=consumer_net.id)
default = gcp.networkconnectivity.ServiceConnectionPolicy("default",
    name="my-policy",
    location="us-central1",
    service_class="gcp-memorystore-redis",
    description="my basic service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [consumer_subnet.id],
    })
cluster_aof = gcp.redis.Cluster("cluster-aof",
    name="aof-cluster",
    shard_count=3,
    psc_configs=[{
        "network": consumer_net.id,
    }],
    region="us-central1",
    replica_count=0,
    node_type="REDIS_SHARED_CORE_NANO",
    transit_encryption_mode="TRANSIT_ENCRYPTION_MODE_DISABLED",
    authorization_mode="AUTH_MODE_DISABLED",
    redis_configs={
        "maxmemory-policy": "volatile-ttl",
    },
    deletion_protection_enabled=True,
    zone_distribution_config={
        "mode": "MULTI_ZONE",
    },
    maintenance_policy={
        "weekly_maintenance_windows": [{
            "day": "MONDAY",
            "start_time": {
                "hours": 1,
                "minutes": 0,
                "seconds": 0,
                "nanos": 0,
            },
        }],
    },
    persistence_config={
        "mode": "AOF",
        "aof_config": {
            "append_fsync": "EVERYSEC",
        },
    },
    opts = pulumi.ResourceOptions(depends_on=[default]))
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		consumerNet, err := compute.NewNetwork(ctx, "consumer_net", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		consumerSubnet, err := compute.NewSubnetwork(ctx, "consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("my-subnet"),
			IpCidrRange: pulumi.String("10.0.0.248/29"),
			Region:      pulumi.String("us-central1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		_default, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "default", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("my-policy"),
			Location:     pulumi.String("us-central1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("my basic service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					consumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = redis.NewCluster(ctx, "cluster-aof", &redis.ClusterArgs{
			Name:       pulumi.String("aof-cluster"),
			ShardCount: pulumi.Int(3),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			Region:                pulumi.String("us-central1"),
			ReplicaCount:          pulumi.Int(0),
			NodeType:              pulumi.String("REDIS_SHARED_CORE_NANO"),
			TransitEncryptionMode: pulumi.String("TRANSIT_ENCRYPTION_MODE_DISABLED"),
			AuthorizationMode:     pulumi.String("AUTH_MODE_DISABLED"),
			RedisConfigs: pulumi.StringMap{
				"maxmemory-policy": pulumi.String("volatile-ttl"),
			},
			DeletionProtectionEnabled: pulumi.Bool(true),
			ZoneDistributionConfig: &redis.ClusterZoneDistributionConfigArgs{
				Mode: pulumi.String("MULTI_ZONE"),
			},
			MaintenancePolicy: &redis.ClusterMaintenancePolicyArgs{
				WeeklyMaintenanceWindows: redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArray{
					&redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs{
						Day: pulumi.String("MONDAY"),
						StartTime: &redis.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs{
							Hours:   pulumi.Int(1),
							Minutes: pulumi.Int(0),
							Seconds: pulumi.Int(0),
							Nanos:   pulumi.Int(0),
						},
					},
				},
			},
			PersistenceConfig: &redis.ClusterPersistenceConfigArgs{
				Mode: pulumi.String("AOF"),
				AofConfig: &redis.ClusterPersistenceConfigAofConfigArgs{
					AppendFsync: pulumi.String("EVERYSEC"),
				},
			},
		}, pulumi.DependsOn([]pulumi.Resource{
			_default,
		}))
		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 consumerNet = new Gcp.Compute.Network("consumer_net", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var consumerSubnet = new Gcp.Compute.Subnetwork("consumer_subnet", new()
    {
        Name = "my-subnet",
        IpCidrRange = "10.0.0.248/29",
        Region = "us-central1",
        Network = consumerNet.Id,
    });

    var @default = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("default", new()
    {
        Name = "my-policy",
        Location = "us-central1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "my basic service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                consumerSubnet.Id,
            },
        },
    });

    var cluster_aof = new Gcp.Redis.Cluster("cluster-aof", new()
    {
        Name = "aof-cluster",
        ShardCount = 3,
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        Region = "us-central1",
        ReplicaCount = 0,
        NodeType = "REDIS_SHARED_CORE_NANO",
        TransitEncryptionMode = "TRANSIT_ENCRYPTION_MODE_DISABLED",
        AuthorizationMode = "AUTH_MODE_DISABLED",
        RedisConfigs = 
        {
            { "maxmemory-policy", "volatile-ttl" },
        },
        DeletionProtectionEnabled = true,
        ZoneDistributionConfig = new Gcp.Redis.Inputs.ClusterZoneDistributionConfigArgs
        {
            Mode = "MULTI_ZONE",
        },
        MaintenancePolicy = new Gcp.Redis.Inputs.ClusterMaintenancePolicyArgs
        {
            WeeklyMaintenanceWindows = new[]
            {
                new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs
                {
                    Day = "MONDAY",
                    StartTime = new Gcp.Redis.Inputs.ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs
                    {
                        Hours = 1,
                        Minutes = 0,
                        Seconds = 0,
                        Nanos = 0,
                    },
                },
            },
        },
        PersistenceConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigArgs
        {
            Mode = "AOF",
            AofConfig = new Gcp.Redis.Inputs.ClusterPersistenceConfigAofConfigArgs
            {
                AppendFsync = "EVERYSEC",
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            @default,
        },
    });

});
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.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicy;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicyArgs;
import com.pulumi.gcp.networkconnectivity.inputs.ServiceConnectionPolicyPscConfigArgs;
import com.pulumi.gcp.redis.Cluster;
import com.pulumi.gcp.redis.ClusterArgs;
import com.pulumi.gcp.redis.inputs.ClusterPscConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterZoneDistributionConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterMaintenancePolicyArgs;
import com.pulumi.gcp.redis.inputs.ClusterPersistenceConfigArgs;
import com.pulumi.gcp.redis.inputs.ClusterPersistenceConfigAofConfigArgs;
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 consumerNet = new Network("consumerNet", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var consumerSubnet = new Subnetwork("consumerSubnet", SubnetworkArgs.builder()
            .name("my-subnet")
            .ipCidrRange("10.0.0.248/29")
            .region("us-central1")
            .network(consumerNet.id())
            .build());

        var default_ = new ServiceConnectionPolicy("default", ServiceConnectionPolicyArgs.builder()
            .name("my-policy")
            .location("us-central1")
            .serviceClass("gcp-memorystore-redis")
            .description("my basic service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(consumerSubnet.id())
                .build())
            .build());

        var cluster_aof = new Cluster("cluster-aof", ClusterArgs.builder()
            .name("aof-cluster")
            .shardCount(3)
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .region("us-central1")
            .replicaCount(0)
            .nodeType("REDIS_SHARED_CORE_NANO")
            .transitEncryptionMode("TRANSIT_ENCRYPTION_MODE_DISABLED")
            .authorizationMode("AUTH_MODE_DISABLED")
            .redisConfigs(Map.of("maxmemory-policy", "volatile-ttl"))
            .deletionProtectionEnabled(true)
            .zoneDistributionConfig(ClusterZoneDistributionConfigArgs.builder()
                .mode("MULTI_ZONE")
                .build())
            .maintenancePolicy(ClusterMaintenancePolicyArgs.builder()
                .weeklyMaintenanceWindows(ClusterMaintenancePolicyWeeklyMaintenanceWindowArgs.builder()
                    .day("MONDAY")
                    .startTime(ClusterMaintenancePolicyWeeklyMaintenanceWindowStartTimeArgs.builder()
                        .hours(1)
                        .minutes(0)
                        .seconds(0)
                        .nanos(0)
                        .build())
                    .build())
                .build())
            .persistenceConfig(ClusterPersistenceConfigArgs.builder()
                .mode("AOF")
                .aofConfig(ClusterPersistenceConfigAofConfigArgs.builder()
                    .appendFsync("EVERYSEC")
                    .build())
                .build())
            .build(), CustomResourceOptions.builder()
                .dependsOn(default_)
                .build());

    }
}
resources:
  cluster-aof:
    type: gcp:redis:Cluster
    properties:
      name: aof-cluster
      shardCount: 3
      pscConfigs:
        - network: ${consumerNet.id}
      region: us-central1
      replicaCount: 0
      nodeType: REDIS_SHARED_CORE_NANO
      transitEncryptionMode: TRANSIT_ENCRYPTION_MODE_DISABLED
      authorizationMode: AUTH_MODE_DISABLED
      redisConfigs:
        maxmemory-policy: volatile-ttl
      deletionProtectionEnabled: true
      zoneDistributionConfig:
        mode: MULTI_ZONE
      maintenancePolicy:
        weeklyMaintenanceWindows:
          - day: MONDAY
            startTime:
              hours: 1
              minutes: 0
              seconds: 0
              nanos: 0
      persistenceConfig:
        mode: AOF
        aofConfig:
          appendFsync: EVERYSEC
    options:
      dependsOn:
        - ${default}
  default:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    properties:
      name: my-policy
      location: us-central1
      serviceClass: gcp-memorystore-redis
      description: my basic service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${consumerSubnet.id}
  consumerSubnet:
    type: gcp:compute:Subnetwork
    name: consumer_subnet
    properties:
      name: my-subnet
      ipCidrRange: 10.0.0.248/29
      region: us-central1
      network: ${consumerNet.id}
  consumerNet:
    type: gcp:compute:Network
    name: consumer_net
    properties:
      name: my-network
      autoCreateSubnetworks: false

Setting persistenceConfig.mode to AOF enables append-only file logging. The appendFsync property controls when writes are flushed to disk: EVERYSEC flushes every second (balancing durability and performance), while ALWAYS flushes after every write (maximum durability, higher latency). AOF provides stronger guarantees than RDB but uses more disk I/O.

Encrypt data with customer-managed keys

Organizations with strict compliance requirements use customer-managed encryption keys to maintain control over data encryption and key rotation policies.

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

const consumerNet = new gcp.compute.Network("consumer_net", {
    name: "my-network",
    autoCreateSubnetworks: false,
});
const consumerSubnet = new gcp.compute.Subnetwork("consumer_subnet", {
    name: "my-subnet",
    ipCidrRange: "10.0.0.248/29",
    region: "us-central1",
    network: consumerNet.id,
});
const _default = new gcp.networkconnectivity.ServiceConnectionPolicy("default", {
    name: "my-policy",
    location: "us-central1",
    serviceClass: "gcp-memorystore-redis",
    description: "my basic service connection policy",
    network: consumerNet.id,
    pscConfig: {
        subnetworks: [consumerSubnet.id],
    },
});
const cluster_cmek = new gcp.redis.Cluster("cluster-cmek", {
    name: "cmek-cluster",
    shardCount: 3,
    pscConfigs: [{
        network: consumerNet.id,
    }],
    kmsKey: "my-key",
    region: "us-central1",
    deletionProtectionEnabled: true,
}, {
    dependsOn: [_default],
});
const project = gcp.organizations.getProject({});
import pulumi
import pulumi_gcp as gcp

consumer_net = gcp.compute.Network("consumer_net",
    name="my-network",
    auto_create_subnetworks=False)
consumer_subnet = gcp.compute.Subnetwork("consumer_subnet",
    name="my-subnet",
    ip_cidr_range="10.0.0.248/29",
    region="us-central1",
    network=consumer_net.id)
default = gcp.networkconnectivity.ServiceConnectionPolicy("default",
    name="my-policy",
    location="us-central1",
    service_class="gcp-memorystore-redis",
    description="my basic service connection policy",
    network=consumer_net.id,
    psc_config={
        "subnetworks": [consumer_subnet.id],
    })
cluster_cmek = gcp.redis.Cluster("cluster-cmek",
    name="cmek-cluster",
    shard_count=3,
    psc_configs=[{
        "network": consumer_net.id,
    }],
    kms_key="my-key",
    region="us-central1",
    deletion_protection_enabled=True,
    opts = pulumi.ResourceOptions(depends_on=[default]))
project = gcp.organizations.get_project()
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		consumerNet, err := compute.NewNetwork(ctx, "consumer_net", &compute.NetworkArgs{
			Name:                  pulumi.String("my-network"),
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}
		consumerSubnet, err := compute.NewSubnetwork(ctx, "consumer_subnet", &compute.SubnetworkArgs{
			Name:        pulumi.String("my-subnet"),
			IpCidrRange: pulumi.String("10.0.0.248/29"),
			Region:      pulumi.String("us-central1"),
			Network:     consumerNet.ID(),
		})
		if err != nil {
			return err
		}
		_default, err := networkconnectivity.NewServiceConnectionPolicy(ctx, "default", &networkconnectivity.ServiceConnectionPolicyArgs{
			Name:         pulumi.String("my-policy"),
			Location:     pulumi.String("us-central1"),
			ServiceClass: pulumi.String("gcp-memorystore-redis"),
			Description:  pulumi.String("my basic service connection policy"),
			Network:      consumerNet.ID(),
			PscConfig: &networkconnectivity.ServiceConnectionPolicyPscConfigArgs{
				Subnetworks: pulumi.StringArray{
					consumerSubnet.ID(),
				},
			},
		})
		if err != nil {
			return err
		}
		_, err = redis.NewCluster(ctx, "cluster-cmek", &redis.ClusterArgs{
			Name:       pulumi.String("cmek-cluster"),
			ShardCount: pulumi.Int(3),
			PscConfigs: redis.ClusterPscConfigArray{
				&redis.ClusterPscConfigArgs{
					Network: consumerNet.ID(),
				},
			},
			KmsKey:                    pulumi.String("my-key"),
			Region:                    pulumi.String("us-central1"),
			DeletionProtectionEnabled: pulumi.Bool(true),
		}, pulumi.DependsOn([]pulumi.Resource{
			_default,
		}))
		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 consumerNet = new Gcp.Compute.Network("consumer_net", new()
    {
        Name = "my-network",
        AutoCreateSubnetworks = false,
    });

    var consumerSubnet = new Gcp.Compute.Subnetwork("consumer_subnet", new()
    {
        Name = "my-subnet",
        IpCidrRange = "10.0.0.248/29",
        Region = "us-central1",
        Network = consumerNet.Id,
    });

    var @default = new Gcp.NetworkConnectivity.ServiceConnectionPolicy("default", new()
    {
        Name = "my-policy",
        Location = "us-central1",
        ServiceClass = "gcp-memorystore-redis",
        Description = "my basic service connection policy",
        Network = consumerNet.Id,
        PscConfig = new Gcp.NetworkConnectivity.Inputs.ServiceConnectionPolicyPscConfigArgs
        {
            Subnetworks = new[]
            {
                consumerSubnet.Id,
            },
        },
    });

    var cluster_cmek = new Gcp.Redis.Cluster("cluster-cmek", new()
    {
        Name = "cmek-cluster",
        ShardCount = 3,
        PscConfigs = new[]
        {
            new Gcp.Redis.Inputs.ClusterPscConfigArgs
            {
                Network = consumerNet.Id,
            },
        },
        KmsKey = "my-key",
        Region = "us-central1",
        DeletionProtectionEnabled = true,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            @default,
        },
    });

    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.compute.Subnetwork;
import com.pulumi.gcp.compute.SubnetworkArgs;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicy;
import com.pulumi.gcp.networkconnectivity.ServiceConnectionPolicyArgs;
import com.pulumi.gcp.networkconnectivity.inputs.ServiceConnectionPolicyPscConfigArgs;
import com.pulumi.gcp.redis.Cluster;
import com.pulumi.gcp.redis.ClusterArgs;
import com.pulumi.gcp.redis.inputs.ClusterPscConfigArgs;
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 consumerNet = new Network("consumerNet", NetworkArgs.builder()
            .name("my-network")
            .autoCreateSubnetworks(false)
            .build());

        var consumerSubnet = new Subnetwork("consumerSubnet", SubnetworkArgs.builder()
            .name("my-subnet")
            .ipCidrRange("10.0.0.248/29")
            .region("us-central1")
            .network(consumerNet.id())
            .build());

        var default_ = new ServiceConnectionPolicy("default", ServiceConnectionPolicyArgs.builder()
            .name("my-policy")
            .location("us-central1")
            .serviceClass("gcp-memorystore-redis")
            .description("my basic service connection policy")
            .network(consumerNet.id())
            .pscConfig(ServiceConnectionPolicyPscConfigArgs.builder()
                .subnetworks(consumerSubnet.id())
                .build())
            .build());

        var cluster_cmek = new Cluster("cluster-cmek", ClusterArgs.builder()
            .name("cmek-cluster")
            .shardCount(3)
            .pscConfigs(ClusterPscConfigArgs.builder()
                .network(consumerNet.id())
                .build())
            .kmsKey("my-key")
            .region("us-central1")
            .deletionProtectionEnabled(true)
            .build(), CustomResourceOptions.builder()
                .dependsOn(default_)
                .build());

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

    }
}
resources:
  cluster-cmek:
    type: gcp:redis:Cluster
    properties:
      name: cmek-cluster
      shardCount: 3
      pscConfigs:
        - network: ${consumerNet.id}
      kmsKey: my-key
      region: us-central1
      deletionProtectionEnabled: true
    options:
      dependsOn:
        - ${default}
  default:
    type: gcp:networkconnectivity:ServiceConnectionPolicy
    properties:
      name: my-policy
      location: us-central1
      serviceClass: gcp-memorystore-redis
      description: my basic service connection policy
      network: ${consumerNet.id}
      pscConfig:
        subnetworks:
          - ${consumerSubnet.id}
  consumerSubnet:
    type: gcp:compute:Subnetwork
    name: consumer_subnet
    properties:
      name: my-subnet
      ipCidrRange: 10.0.0.248/29
      region: us-central1
      network: ${consumerNet.id}
  consumerNet:
    type: gcp:compute:Network
    name: consumer_net
    properties:
      name: my-network
      autoCreateSubnetworks: false
variables:
  project:
    fn::invoke:
      function: gcp:organizations:getProject
      arguments: {}

The kmsKey property references a Cloud KMS key for encrypting cluster data at rest. You control key rotation, access policies, and audit logging through Cloud KMS. The cluster service account needs cryptoKeyEncrypterDecrypter permissions on the key. This satisfies compliance requirements that prohibit Google-managed encryption keys.

Beyond these examples

These snippets focus on specific cluster-level features: high availability and zone distribution, cross-region replication, persistence (RDB snapshots and AOF logging), and customer-managed encryption. They’re intentionally minimal rather than full Redis deployments.

The examples reference pre-existing infrastructure such as VPC networks and subnets, ServiceConnectionPolicy for PSC connectivity, KMS keys (for CMEK example), and primary clusters (for secondary cluster example). They focus on configuring the cluster rather than provisioning the surrounding network infrastructure.

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

  • Labels and resource tagging
  • Redis configuration parameters (redisConfigs)
  • Maintenance windows and version management
  • Authorization modes (IAM vs disabled)
  • Transit encryption and TLS configuration
  • Automated backup configuration

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

Let's deploy GCP Cloud Memorystore Redis Clusters

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Cross-Region Replication
How do I perform a switchover between primary and secondary clusters?
Update the secondary cluster’s crossClusterReplicationConfig: change clusterRole from SECONDARY to PRIMARY, remove primaryCluster, and set secondaryCluster list with the new secondaries. Run pulumi up, then manually sync configuration drift on other clusters by updating their config files with values from state.
How do I detach a secondary cluster from replication?
You have two options: (1) Update the secondary’s crossClusterReplicationConfig by changing clusterRole to NONE and removing primaryCluster, or (2) Update the primary’s secondaryCluster list to remove the secondary. After running pulumi up, manually reconcile configuration drift on affected clusters.
Why do I need to manually sync configuration after replication operations?
Some settings are automatically propagated from primary to secondary clusters. After switchover or detach operations, pulumi preview will show drift that must be resolved by manually updating configuration files with the latest values from state.
Which settings are automatically propagated from primary to secondary clusters?
Settings listed in the GCP documentation are updated on the primary and automatically propagated to secondaries. To keep Pulumi configuration in sync, update the primary first, then manually update secondary configuration files with the new values from state.
Networking & Connectivity
Why do I need to create a ServiceConnectionPolicy before my cluster?
Redis clusters require a gcp.networkconnectivity.ServiceConnectionPolicy for Private Service Connect (PSC) networking. All examples show this as a dependency using dependsOn.
Can I configure multiple PSC networks for my cluster?
Currently, only one pscConfig is supported per cluster, even though the property accepts an array.
When should I use ClusterUserCreatedConnections instead of the standard cluster resource?
Use gcp.redis.ClusterUserCreatedConnections when you need User-registered PSC Connections for Multiple VPC Networking scenarios.
Security & Encryption
How do I enable authentication and encryption for my cluster?
Set authorizationMode (e.g., AUTH_MODE_IAM_AUTH) and transitEncryptionMode (e.g., TRANSIT_ENCRYPTION_MODE_SERVER_AUTHENTICATION). Both are immutable and default to disabled, so configure them during initial creation.
How do I use customer-managed encryption keys for data at rest?
Set the kmsKey property to your Cloud KMS key resource name.
Can I use my own certificate authority for TLS?
Yes, set transitEncryptionMode to TRANSIT_ENCRYPTION_MODE_SERVER_AUTHENTICATION, serverCaMode to SERVER_CA_MODE_CUSTOMER_MANAGED_CAS_CA, and serverCaPool to your Certificate Authority Service pool ID.
High Availability & Persistence
What's the difference between RDB and AOF persistence modes?
RDB creates periodic snapshots configured with rdbSnapshotPeriod (e.g., ONE_HOUR), while AOF appends every write operation with configurable sync frequency via appendFsync (e.g., EVERYSEC).
How do I configure high availability with replicas?
Set replicaCount to the desired number of replica nodes per shard (e.g., 1 or 2). Configure zoneDistributionConfig with mode: MULTI_ZONE to distribute replicas across zones.
Configuration & Maintenance
What properties can't I change after creating my cluster?
These properties are immutable: name, project, region, zoneDistributionConfig, authorizationMode, transitEncryptionMode, gcsSource, and managedBackupSource. Plan these carefully during initial creation.
Can I downgrade my cluster's maintenance version?
No, the maintenanceVersion field only supports upgrades to newer versions. Downgrades are not currently supported.
Is deletion protection enabled by default?
Yes, deletionProtectionEnabled defaults to true. Any delete operation will fail unless you explicitly set this to false.

Using a different cloud?

Explore database guides for other cloud providers: