Create GCP Backup and Disaster Recovery Plans

The gcp:backupdisasterrecovery/backupPlan:BackupPlan resource, part of the Pulumi GCP provider, defines backup schedules, retention policies, and storage locations for GCP resources. This guide focuses on three capabilities: Compute Engine instance backups, persistent disk backups, and Cloud SQL backups with transaction logs.

Backup plans depend on a BackupVault that must exist before creating the plan. The examples are intentionally small. Combine them with your own vault configuration and resource targeting.

Schedule hourly backups for Compute Engine instances

Teams protecting VM workloads start with a backup plan that captures instance state on a regular schedule.

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

const myBackupVault = new gcp.backupdisasterrecovery.BackupVault("my_backup_vault", {
    location: "us-central1",
    backupVaultId: "backup-vault-simple-test",
    backupMinimumEnforcedRetentionDuration: "100000s",
});
const my_backup_plan_1 = new gcp.backupdisasterrecovery.BackupPlan("my-backup-plan-1", {
    location: "us-central1",
    backupPlanId: "backup-plan-simple-test",
    resourceType: "compute.googleapis.com/Instance",
    backupVault: myBackupVault.id,
    backupRules: [{
        ruleId: "rule-1",
        backupRetentionDays: 5,
        standardSchedule: {
            recurrenceType: "HOURLY",
            hourlyFrequency: 6,
            timeZone: "UTC",
            backupWindow: {
                startHourOfDay: 0,
                endHourOfDay: 24,
            },
        },
    }],
});
import pulumi
import pulumi_gcp as gcp

my_backup_vault = gcp.backupdisasterrecovery.BackupVault("my_backup_vault",
    location="us-central1",
    backup_vault_id="backup-vault-simple-test",
    backup_minimum_enforced_retention_duration="100000s")
my_backup_plan_1 = gcp.backupdisasterrecovery.BackupPlan("my-backup-plan-1",
    location="us-central1",
    backup_plan_id="backup-plan-simple-test",
    resource_type="compute.googleapis.com/Instance",
    backup_vault=my_backup_vault.id,
    backup_rules=[{
        "rule_id": "rule-1",
        "backup_retention_days": 5,
        "standard_schedule": {
            "recurrence_type": "HOURLY",
            "hourly_frequency": 6,
            "time_zone": "UTC",
            "backup_window": {
                "start_hour_of_day": 0,
                "end_hour_of_day": 24,
            },
        },
    }])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/backupdisasterrecovery"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myBackupVault, err := backupdisasterrecovery.NewBackupVault(ctx, "my_backup_vault", &backupdisasterrecovery.BackupVaultArgs{
			Location:                               pulumi.String("us-central1"),
			BackupVaultId:                          pulumi.String("backup-vault-simple-test"),
			BackupMinimumEnforcedRetentionDuration: pulumi.String("100000s"),
		})
		if err != nil {
			return err
		}
		_, err = backupdisasterrecovery.NewBackupPlan(ctx, "my-backup-plan-1", &backupdisasterrecovery.BackupPlanArgs{
			Location:     pulumi.String("us-central1"),
			BackupPlanId: pulumi.String("backup-plan-simple-test"),
			ResourceType: pulumi.String("compute.googleapis.com/Instance"),
			BackupVault:  myBackupVault.ID(),
			BackupRules: backupdisasterrecovery.BackupPlanBackupRuleArray{
				&backupdisasterrecovery.BackupPlanBackupRuleArgs{
					RuleId:              pulumi.String("rule-1"),
					BackupRetentionDays: pulumi.Int(5),
					StandardSchedule: &backupdisasterrecovery.BackupPlanBackupRuleStandardScheduleArgs{
						RecurrenceType:  pulumi.String("HOURLY"),
						HourlyFrequency: pulumi.Int(6),
						TimeZone:        pulumi.String("UTC"),
						BackupWindow: &backupdisasterrecovery.BackupPlanBackupRuleStandardScheduleBackupWindowArgs{
							StartHourOfDay: pulumi.Int(0),
							EndHourOfDay:   pulumi.Int(24),
						},
					},
				},
			},
		})
		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 myBackupVault = new Gcp.BackupDisasterRecovery.BackupVault("my_backup_vault", new()
    {
        Location = "us-central1",
        BackupVaultId = "backup-vault-simple-test",
        BackupMinimumEnforcedRetentionDuration = "100000s",
    });

    var my_backup_plan_1 = new Gcp.BackupDisasterRecovery.BackupPlan("my-backup-plan-1", new()
    {
        Location = "us-central1",
        BackupPlanId = "backup-plan-simple-test",
        ResourceType = "compute.googleapis.com/Instance",
        BackupVault = myBackupVault.Id,
        BackupRules = new[]
        {
            new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleArgs
            {
                RuleId = "rule-1",
                BackupRetentionDays = 5,
                StandardSchedule = new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleStandardScheduleArgs
                {
                    RecurrenceType = "HOURLY",
                    HourlyFrequency = 6,
                    TimeZone = "UTC",
                    BackupWindow = new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleStandardScheduleBackupWindowArgs
                    {
                        StartHourOfDay = 0,
                        EndHourOfDay = 24,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.backupdisasterrecovery.BackupVault;
import com.pulumi.gcp.backupdisasterrecovery.BackupVaultArgs;
import com.pulumi.gcp.backupdisasterrecovery.BackupPlan;
import com.pulumi.gcp.backupdisasterrecovery.BackupPlanArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleStandardScheduleArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleStandardScheduleBackupWindowArgs;
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 myBackupVault = new BackupVault("myBackupVault", BackupVaultArgs.builder()
            .location("us-central1")
            .backupVaultId("backup-vault-simple-test")
            .backupMinimumEnforcedRetentionDuration("100000s")
            .build());

        var my_backup_plan_1 = new BackupPlan("my-backup-plan-1", BackupPlanArgs.builder()
            .location("us-central1")
            .backupPlanId("backup-plan-simple-test")
            .resourceType("compute.googleapis.com/Instance")
            .backupVault(myBackupVault.id())
            .backupRules(BackupPlanBackupRuleArgs.builder()
                .ruleId("rule-1")
                .backupRetentionDays(5)
                .standardSchedule(BackupPlanBackupRuleStandardScheduleArgs.builder()
                    .recurrenceType("HOURLY")
                    .hourlyFrequency(6)
                    .timeZone("UTC")
                    .backupWindow(BackupPlanBackupRuleStandardScheduleBackupWindowArgs.builder()
                        .startHourOfDay(0)
                        .endHourOfDay(24)
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  myBackupVault:
    type: gcp:backupdisasterrecovery:BackupVault
    name: my_backup_vault
    properties:
      location: us-central1
      backupVaultId: backup-vault-simple-test
      backupMinimumEnforcedRetentionDuration: 100000s
  my-backup-plan-1:
    type: gcp:backupdisasterrecovery:BackupPlan
    properties:
      location: us-central1
      backupPlanId: backup-plan-simple-test
      resourceType: compute.googleapis.com/Instance
      backupVault: ${myBackupVault.id}
      backupRules:
        - ruleId: rule-1
          backupRetentionDays: 5
          standardSchedule:
            recurrenceType: HOURLY
            hourlyFrequency: 6
            timeZone: UTC
            backupWindow:
              startHourOfDay: 0
              endHourOfDay: 24

The resourceType property targets Compute Engine instances. The backupRules array defines when backups occur: recurrenceType sets the frequency (HOURLY, DAILY, WEEKLY), hourlyFrequency controls how often within that period, and backupRetentionDays determines how long snapshots are kept. The backupWindow restricts when backups can start, useful for avoiding peak usage hours.

Back up persistent disks independently

Persistent disks can be backed up separately from their attached instances, enabling granular recovery.

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

const myBackupVault = new gcp.backupdisasterrecovery.BackupVault("my_backup_vault", {
    location: "us-central1",
    backupVaultId: "backup-vault-disk-test",
    backupMinimumEnforcedRetentionDuration: "100000s",
});
const my_disk_backup_plan_1 = new gcp.backupdisasterrecovery.BackupPlan("my-disk-backup-plan-1", {
    location: "us-central1",
    backupPlanId: "backup-plan-disk-test",
    resourceType: "compute.googleapis.com/Disk",
    backupVault: myBackupVault.id,
    backupRules: [{
        ruleId: "rule-1",
        backupRetentionDays: 5,
        standardSchedule: {
            recurrenceType: "HOURLY",
            hourlyFrequency: 1,
            timeZone: "UTC",
            backupWindow: {
                startHourOfDay: 0,
                endHourOfDay: 6,
            },
        },
    }],
});
import pulumi
import pulumi_gcp as gcp

my_backup_vault = gcp.backupdisasterrecovery.BackupVault("my_backup_vault",
    location="us-central1",
    backup_vault_id="backup-vault-disk-test",
    backup_minimum_enforced_retention_duration="100000s")
my_disk_backup_plan_1 = gcp.backupdisasterrecovery.BackupPlan("my-disk-backup-plan-1",
    location="us-central1",
    backup_plan_id="backup-plan-disk-test",
    resource_type="compute.googleapis.com/Disk",
    backup_vault=my_backup_vault.id,
    backup_rules=[{
        "rule_id": "rule-1",
        "backup_retention_days": 5,
        "standard_schedule": {
            "recurrence_type": "HOURLY",
            "hourly_frequency": 1,
            "time_zone": "UTC",
            "backup_window": {
                "start_hour_of_day": 0,
                "end_hour_of_day": 6,
            },
        },
    }])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/backupdisasterrecovery"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myBackupVault, err := backupdisasterrecovery.NewBackupVault(ctx, "my_backup_vault", &backupdisasterrecovery.BackupVaultArgs{
			Location:                               pulumi.String("us-central1"),
			BackupVaultId:                          pulumi.String("backup-vault-disk-test"),
			BackupMinimumEnforcedRetentionDuration: pulumi.String("100000s"),
		})
		if err != nil {
			return err
		}
		_, err = backupdisasterrecovery.NewBackupPlan(ctx, "my-disk-backup-plan-1", &backupdisasterrecovery.BackupPlanArgs{
			Location:     pulumi.String("us-central1"),
			BackupPlanId: pulumi.String("backup-plan-disk-test"),
			ResourceType: pulumi.String("compute.googleapis.com/Disk"),
			BackupVault:  myBackupVault.ID(),
			BackupRules: backupdisasterrecovery.BackupPlanBackupRuleArray{
				&backupdisasterrecovery.BackupPlanBackupRuleArgs{
					RuleId:              pulumi.String("rule-1"),
					BackupRetentionDays: pulumi.Int(5),
					StandardSchedule: &backupdisasterrecovery.BackupPlanBackupRuleStandardScheduleArgs{
						RecurrenceType:  pulumi.String("HOURLY"),
						HourlyFrequency: pulumi.Int(1),
						TimeZone:        pulumi.String("UTC"),
						BackupWindow: &backupdisasterrecovery.BackupPlanBackupRuleStandardScheduleBackupWindowArgs{
							StartHourOfDay: pulumi.Int(0),
							EndHourOfDay:   pulumi.Int(6),
						},
					},
				},
			},
		})
		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 myBackupVault = new Gcp.BackupDisasterRecovery.BackupVault("my_backup_vault", new()
    {
        Location = "us-central1",
        BackupVaultId = "backup-vault-disk-test",
        BackupMinimumEnforcedRetentionDuration = "100000s",
    });

    var my_disk_backup_plan_1 = new Gcp.BackupDisasterRecovery.BackupPlan("my-disk-backup-plan-1", new()
    {
        Location = "us-central1",
        BackupPlanId = "backup-plan-disk-test",
        ResourceType = "compute.googleapis.com/Disk",
        BackupVault = myBackupVault.Id,
        BackupRules = new[]
        {
            new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleArgs
            {
                RuleId = "rule-1",
                BackupRetentionDays = 5,
                StandardSchedule = new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleStandardScheduleArgs
                {
                    RecurrenceType = "HOURLY",
                    HourlyFrequency = 1,
                    TimeZone = "UTC",
                    BackupWindow = new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleStandardScheduleBackupWindowArgs
                    {
                        StartHourOfDay = 0,
                        EndHourOfDay = 6,
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.backupdisasterrecovery.BackupVault;
import com.pulumi.gcp.backupdisasterrecovery.BackupVaultArgs;
import com.pulumi.gcp.backupdisasterrecovery.BackupPlan;
import com.pulumi.gcp.backupdisasterrecovery.BackupPlanArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleStandardScheduleArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleStandardScheduleBackupWindowArgs;
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 myBackupVault = new BackupVault("myBackupVault", BackupVaultArgs.builder()
            .location("us-central1")
            .backupVaultId("backup-vault-disk-test")
            .backupMinimumEnforcedRetentionDuration("100000s")
            .build());

        var my_disk_backup_plan_1 = new BackupPlan("my-disk-backup-plan-1", BackupPlanArgs.builder()
            .location("us-central1")
            .backupPlanId("backup-plan-disk-test")
            .resourceType("compute.googleapis.com/Disk")
            .backupVault(myBackupVault.id())
            .backupRules(BackupPlanBackupRuleArgs.builder()
                .ruleId("rule-1")
                .backupRetentionDays(5)
                .standardSchedule(BackupPlanBackupRuleStandardScheduleArgs.builder()
                    .recurrenceType("HOURLY")
                    .hourlyFrequency(1)
                    .timeZone("UTC")
                    .backupWindow(BackupPlanBackupRuleStandardScheduleBackupWindowArgs.builder()
                        .startHourOfDay(0)
                        .endHourOfDay(6)
                        .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  myBackupVault:
    type: gcp:backupdisasterrecovery:BackupVault
    name: my_backup_vault
    properties:
      location: us-central1
      backupVaultId: backup-vault-disk-test
      backupMinimumEnforcedRetentionDuration: 100000s
  my-disk-backup-plan-1:
    type: gcp:backupdisasterrecovery:BackupPlan
    properties:
      location: us-central1
      backupPlanId: backup-plan-disk-test
      resourceType: compute.googleapis.com/Disk
      backupVault: ${myBackupVault.id}
      backupRules:
        - ruleId: rule-1
          backupRetentionDays: 5
          standardSchedule:
            recurrenceType: HOURLY
            hourlyFrequency: 1
            timeZone: UTC
            backupWindow:
              startHourOfDay: 0
              endHourOfDay: 6

Changing resourceType to “compute.googleapis.com/Disk” targets persistent disks instead of instances. The backupWindow narrows to a 6-hour window (0-6 UTC), demonstrating how to constrain backup timing. This configuration backs up disks every hour during that window, retaining each snapshot for 5 days.

Protect Cloud SQL with transaction log retention

Database workloads need both snapshot backups and transaction log retention for point-in-time recovery.

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

const myBackupVault = new gcp.backupdisasterrecovery.BackupVault("my_backup_vault", {
    location: "us-central1",
    backupVaultId: "backup-vault-csql-test",
    backupMinimumEnforcedRetentionDuration: "100000s",
});
const my_csql_backup_plan_1 = new gcp.backupdisasterrecovery.BackupPlan("my-csql-backup-plan-1", {
    location: "us-central1",
    backupPlanId: "backup-plan-csql-test",
    resourceType: "sqladmin.googleapis.com/Instance",
    backupVault: myBackupVault.id,
    backupRules: [{
        ruleId: "rule-1",
        backupRetentionDays: 5,
        standardSchedule: {
            recurrenceType: "HOURLY",
            hourlyFrequency: 6,
            timeZone: "UTC",
            backupWindow: {
                startHourOfDay: 0,
                endHourOfDay: 6,
            },
        },
    }],
    logRetentionDays: 4,
});
import pulumi
import pulumi_gcp as gcp

my_backup_vault = gcp.backupdisasterrecovery.BackupVault("my_backup_vault",
    location="us-central1",
    backup_vault_id="backup-vault-csql-test",
    backup_minimum_enforced_retention_duration="100000s")
my_csql_backup_plan_1 = gcp.backupdisasterrecovery.BackupPlan("my-csql-backup-plan-1",
    location="us-central1",
    backup_plan_id="backup-plan-csql-test",
    resource_type="sqladmin.googleapis.com/Instance",
    backup_vault=my_backup_vault.id,
    backup_rules=[{
        "rule_id": "rule-1",
        "backup_retention_days": 5,
        "standard_schedule": {
            "recurrence_type": "HOURLY",
            "hourly_frequency": 6,
            "time_zone": "UTC",
            "backup_window": {
                "start_hour_of_day": 0,
                "end_hour_of_day": 6,
            },
        },
    }],
    log_retention_days=4)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/backupdisasterrecovery"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myBackupVault, err := backupdisasterrecovery.NewBackupVault(ctx, "my_backup_vault", &backupdisasterrecovery.BackupVaultArgs{
			Location:                               pulumi.String("us-central1"),
			BackupVaultId:                          pulumi.String("backup-vault-csql-test"),
			BackupMinimumEnforcedRetentionDuration: pulumi.String("100000s"),
		})
		if err != nil {
			return err
		}
		_, err = backupdisasterrecovery.NewBackupPlan(ctx, "my-csql-backup-plan-1", &backupdisasterrecovery.BackupPlanArgs{
			Location:     pulumi.String("us-central1"),
			BackupPlanId: pulumi.String("backup-plan-csql-test"),
			ResourceType: pulumi.String("sqladmin.googleapis.com/Instance"),
			BackupVault:  myBackupVault.ID(),
			BackupRules: backupdisasterrecovery.BackupPlanBackupRuleArray{
				&backupdisasterrecovery.BackupPlanBackupRuleArgs{
					RuleId:              pulumi.String("rule-1"),
					BackupRetentionDays: pulumi.Int(5),
					StandardSchedule: &backupdisasterrecovery.BackupPlanBackupRuleStandardScheduleArgs{
						RecurrenceType:  pulumi.String("HOURLY"),
						HourlyFrequency: pulumi.Int(6),
						TimeZone:        pulumi.String("UTC"),
						BackupWindow: &backupdisasterrecovery.BackupPlanBackupRuleStandardScheduleBackupWindowArgs{
							StartHourOfDay: pulumi.Int(0),
							EndHourOfDay:   pulumi.Int(6),
						},
					},
				},
			},
			LogRetentionDays: pulumi.Int(4),
		})
		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 myBackupVault = new Gcp.BackupDisasterRecovery.BackupVault("my_backup_vault", new()
    {
        Location = "us-central1",
        BackupVaultId = "backup-vault-csql-test",
        BackupMinimumEnforcedRetentionDuration = "100000s",
    });

    var my_csql_backup_plan_1 = new Gcp.BackupDisasterRecovery.BackupPlan("my-csql-backup-plan-1", new()
    {
        Location = "us-central1",
        BackupPlanId = "backup-plan-csql-test",
        ResourceType = "sqladmin.googleapis.com/Instance",
        BackupVault = myBackupVault.Id,
        BackupRules = new[]
        {
            new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleArgs
            {
                RuleId = "rule-1",
                BackupRetentionDays = 5,
                StandardSchedule = new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleStandardScheduleArgs
                {
                    RecurrenceType = "HOURLY",
                    HourlyFrequency = 6,
                    TimeZone = "UTC",
                    BackupWindow = new Gcp.BackupDisasterRecovery.Inputs.BackupPlanBackupRuleStandardScheduleBackupWindowArgs
                    {
                        StartHourOfDay = 0,
                        EndHourOfDay = 6,
                    },
                },
            },
        },
        LogRetentionDays = 4,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.backupdisasterrecovery.BackupVault;
import com.pulumi.gcp.backupdisasterrecovery.BackupVaultArgs;
import com.pulumi.gcp.backupdisasterrecovery.BackupPlan;
import com.pulumi.gcp.backupdisasterrecovery.BackupPlanArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleStandardScheduleArgs;
import com.pulumi.gcp.backupdisasterrecovery.inputs.BackupPlanBackupRuleStandardScheduleBackupWindowArgs;
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 myBackupVault = new BackupVault("myBackupVault", BackupVaultArgs.builder()
            .location("us-central1")
            .backupVaultId("backup-vault-csql-test")
            .backupMinimumEnforcedRetentionDuration("100000s")
            .build());

        var my_csql_backup_plan_1 = new BackupPlan("my-csql-backup-plan-1", BackupPlanArgs.builder()
            .location("us-central1")
            .backupPlanId("backup-plan-csql-test")
            .resourceType("sqladmin.googleapis.com/Instance")
            .backupVault(myBackupVault.id())
            .backupRules(BackupPlanBackupRuleArgs.builder()
                .ruleId("rule-1")
                .backupRetentionDays(5)
                .standardSchedule(BackupPlanBackupRuleStandardScheduleArgs.builder()
                    .recurrenceType("HOURLY")
                    .hourlyFrequency(6)
                    .timeZone("UTC")
                    .backupWindow(BackupPlanBackupRuleStandardScheduleBackupWindowArgs.builder()
                        .startHourOfDay(0)
                        .endHourOfDay(6)
                        .build())
                    .build())
                .build())
            .logRetentionDays(4)
            .build());

    }
}
resources:
  myBackupVault:
    type: gcp:backupdisasterrecovery:BackupVault
    name: my_backup_vault
    properties:
      location: us-central1
      backupVaultId: backup-vault-csql-test
      backupMinimumEnforcedRetentionDuration: 100000s
  my-csql-backup-plan-1:
    type: gcp:backupdisasterrecovery:BackupPlan
    properties:
      location: us-central1
      backupPlanId: backup-plan-csql-test
      resourceType: sqladmin.googleapis.com/Instance
      backupVault: ${myBackupVault.id}
      backupRules:
        - ruleId: rule-1
          backupRetentionDays: 5
          standardSchedule:
            recurrenceType: HOURLY
            hourlyFrequency: 6
            timeZone: UTC
            backupWindow:
              startHourOfDay: 0
              endHourOfDay: 6
      logRetentionDays: 4

The resourceType switches to “sqladmin.googleapis.com/Instance” for Cloud SQL databases. The logRetentionDays property enables transaction log retention, which is required for point-in-time recovery. This value must meet or exceed the backup vault’s minimum enforced log retention duration.

Beyond these examples

These snippets focus on specific backup plan features: resource-specific backup scheduling, retention policies and backup windows, and transaction log retention for databases. They’re intentionally minimal rather than full disaster recovery solutions.

The examples reference pre-existing infrastructure such as a BackupVault with minimum enforced retention configured. They focus on configuring the backup plan rather than provisioning the vault infrastructure.

To keep things focused, common backup plan patterns are omitted, including:

  • Multiple backup rules per plan
  • Custom backup windows for different time zones
  • Backup plan descriptions and metadata
  • Weekly or monthly recurrence patterns

These omissions are intentional: the goal is to illustrate how each backup plan feature is wired, not provide drop-in disaster recovery modules. See the BackupPlan resource reference for all available configuration options.

Let's create GCP Backup and Disaster Recovery Plans

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Types & Compatibility
What resource types can I back up with a BackupPlan?
You can back up Compute Instances (compute.googleapis.com/Instance), Compute Disks (compute.googleapis.com/Disk), Cloud SQL Instances (sqladmin.googleapis.com/Instance), and Cloud Storage Buckets (storage.googleapis.com/Bucket).
When should I use logRetentionDays?
Use logRetentionDays only for Cloud SQL resources (sqladmin.googleapis.com/Instance). This property specifies how many days logs will be stored and must be greater than or equal to the backup vault’s minimum enforced log retention duration.
Configuration & Scheduling
How many backup rules do I need to define?
At least one BackupRule is required in the backupRules array.
How do I configure hourly backups?
Set standardSchedule with recurrenceType: "HOURLY" and specify hourlyFrequency (e.g., 1 for every hour, 6 for every 6 hours).
How do I control when backups run during the day?
Configure backupWindow within standardSchedule using startHourOfDay and endHourOfDay. For example, setting 0 to 6 restricts backups to the first 6 hours of the day.
What's the difference between backupRetentionDays and logRetentionDays?
backupRetentionDays (in backupRules) controls how long backup snapshots are kept. logRetentionDays is Cloud SQL-specific and controls how long transaction logs are retained.
Immutability & Constraints
What properties can't I change after creating a BackupPlan?
The following properties are immutable: backupPlanId, backupVault, location, project, and logRetentionDays.
Can I change the backup vault after creating a BackupPlan?
No, backupVault is immutable and cannot be changed after creation.
What happens if my logRetentionDays is less than the vault's minimum?
The logRetentionDays value must be greater than or equal to the backup vault’s minimum enforced log retention duration, or the configuration will be invalid.

Using a different cloud?

Explore storage guides for other cloud providers: