Create GCP Backup and Disaster Recovery Plans

The gcp:backupdisasterrecovery/backupPlan:BackupPlan resource, part of the Pulumi GCP provider, defines automated backup schedules, retention policies, and storage locations for GCP resources. This guide focuses on three capabilities: Compute Engine instance and disk backups, Cloud SQL database protection with log retention, and Filestore NFS share snapshots.

Backup plans depend on a BackupVault resource that controls where backups are stored and enforces minimum retention policies. The examples are intentionally small. Combine them with your own vault configuration and resource targeting.

Schedule hourly backups for Compute Engine instances

Most backup strategies start with VM instances, scheduling regular snapshots to protect against data loss or configuration errors.

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,
    maxCustomOnDemandRetentionDays: 30,
    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,
    max_custom_on_demand_retention_days=30,
    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(),
			MaxCustomOnDemandRetentionDays: pulumi.Int(30),
			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,
        MaxCustomOnDemandRetentionDays = 30,
        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())
            .maxCustomOnDemandRetentionDays(30)
            .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}
      maxCustomOnDemandRetentionDays: 30
      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 run: recurrenceType sets the frequency (HOURLY, DAILY, WEEKLY), hourlyFrequency controls how often within that period, and backupRetentionDays determines how long snapshots are kept. The backupVault property points to where backups are stored.

Back up persistent disks independently from instances

Teams managing stateful workloads often need to back up persistent disks separately from the VMs they’re attached to.

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,
    maxCustomOnDemandRetentionDays: 30,
    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,
    max_custom_on_demand_retention_days=30,
    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(),
			MaxCustomOnDemandRetentionDays: pulumi.Int(30),
			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,
        MaxCustomOnDemandRetentionDays = 30,
        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())
            .maxCustomOnDemandRetentionDays(30)
            .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}
      maxCustomOnDemandRetentionDays: 30
      backupRules:
        - ruleId: rule-1
          backupRetentionDays: 5
          standardSchedule:
            recurrenceType: HOURLY
            hourlyFrequency: 1
            timeZone: UTC
            backupWindow:
              startHourOfDay: 0
              endHourOfDay: 6

The resourceType changes to compute.googleapis.com/Disk to target persistent disks. The backupWindow property restricts when backups can run, using startHourOfDay and endHourOfDay to define a maintenance window. This prevents backups from impacting production workloads during peak hours.

Protect Cloud SQL databases with log retention

Database backups require both snapshot protection 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,
    maxCustomOnDemandRetentionDays: 30,
    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,
    max_custom_on_demand_retention_days=30,
    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(),
			MaxCustomOnDemandRetentionDays: pulumi.Int(30),
			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,
        MaxCustomOnDemandRetentionDays = 30,
        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())
            .maxCustomOnDemandRetentionDays(30)
            .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}
      maxCustomOnDemandRetentionDays: 30
      backupRules:
        - ruleId: rule-1
          backupRetentionDays: 5
          standardSchedule:
            recurrenceType: HOURLY
            hourlyFrequency: 6
            timeZone: UTC
            backupWindow:
              startHourOfDay: 0
              endHourOfDay: 6
      logRetentionDays: 4

The resourceType targets Cloud SQL instances using sqladmin.googleapis.com/Instance. The logRetentionDays property enables transaction log archival, which allows point-in-time recovery between scheduled backups. This value must meet or exceed the backup vault’s minimum enforced log retention.

Schedule backups for Filestore NFS shares

Filestore instances provide managed NFS storage that requires regular backups to protect shared file data.

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-filestore-test",
    backupMinimumEnforcedRetentionDuration: "100000s",
});
const my_filestore_backup_plan_1 = new gcp.backupdisasterrecovery.BackupPlan("my-filestore-backup-plan-1", {
    location: "us-central1",
    backupPlanId: "backup-plan-filestore-test",
    resourceType: "file.googleapis.com/Instance",
    backupVault: myBackupVault.id,
    backupRules: [{
        ruleId: "rule-1",
        backupRetentionDays: 5,
        standardSchedule: {
            recurrenceType: "HOURLY",
            hourlyFrequency: 6,
            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-filestore-test",
    backup_minimum_enforced_retention_duration="100000s")
my_filestore_backup_plan_1 = gcp.backupdisasterrecovery.BackupPlan("my-filestore-backup-plan-1",
    location="us-central1",
    backup_plan_id="backup-plan-filestore-test",
    resource_type="file.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,
            },
        },
    }])
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-filestore-test"),
			BackupMinimumEnforcedRetentionDuration: pulumi.String("100000s"),
		})
		if err != nil {
			return err
		}
		_, err = backupdisasterrecovery.NewBackupPlan(ctx, "my-filestore-backup-plan-1", &backupdisasterrecovery.BackupPlanArgs{
			Location:     pulumi.String("us-central1"),
			BackupPlanId: pulumi.String("backup-plan-filestore-test"),
			ResourceType: pulumi.String("file.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),
						},
					},
				},
			},
		})
		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-filestore-test",
        BackupMinimumEnforcedRetentionDuration = "100000s",
    });

    var my_filestore_backup_plan_1 = new Gcp.BackupDisasterRecovery.BackupPlan("my-filestore-backup-plan-1", new()
    {
        Location = "us-central1",
        BackupPlanId = "backup-plan-filestore-test",
        ResourceType = "file.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,
                    },
                },
            },
        },
    });

});
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-filestore-test")
            .backupMinimumEnforcedRetentionDuration("100000s")
            .build());

        var my_filestore_backup_plan_1 = new BackupPlan("my-filestore-backup-plan-1", BackupPlanArgs.builder()
            .location("us-central1")
            .backupPlanId("backup-plan-filestore-test")
            .resourceType("file.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())
            .build());

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

The resourceType targets Filestore instances using file.googleapis.com/Instance. The backup schedule follows the same pattern as other resources, but Filestore backups capture the entire NFS share state, including all files and directories.

Beyond these examples

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

The examples require pre-existing infrastructure such as BackupVault resources with configured retention policies. They focus on configuring backup schedules rather than provisioning the storage infrastructure.

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

  • Custom on-demand backup retention (maxCustomOnDemandRetentionDays)
  • Multiple backup rules per plan
  • Weekly, daily, or custom recurrence schedules
  • Backup plan descriptions and metadata

These omissions are intentional: the goal is to illustrate how each backup 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

Immutability & Limitations
What properties can't I change after creating a backup plan?
The backupPlanId, backupVault, location, project, and logRetentionDays properties are immutable and require resource recreation if changed.
Can I change the backup vault after creating a backup plan?
No, the backupVault property is immutable. You’ll need to create a new backup plan to use a different vault.
What's the logRetentionDays constraint for CloudSql backups?
For CloudSql resources, logRetentionDays must be greater than or equal to the minimum enforced log retention duration of the backup vault. This property is also immutable.
Resource Types & Configuration
What resource types can I back up with a backup plan?
You can back up Compute Engine instances (compute.googleapis.com/Instance), disks (compute.googleapis.com/Disk), CloudSql instances (sqladmin.googleapis.com/Instance), AlloyDB clusters (alloydb.googleapis.com/Cluster), Filestore instances (file.googleapis.com/Instance), and Cloud Storage buckets (storage.googleapis.com/Bucket).
What's required in the backupRules configuration?
The backupRules array must contain at least one BackupRule message. Each rule typically includes a ruleId, backupRetentionDays, and a standardSchedule with recurrence settings.
Backup Scheduling & Retention
How do I configure backup schedules?
Configure standardSchedule within backupRules, specifying recurrenceType (like HOURLY), hourlyFrequency, timeZone, and a backupWindow with start and end hours.
What does maxCustomOnDemandRetentionDays control?
It sets the maximum number of days an on-demand backup with custom retention can be retained. This is optional and shown in most examples with a value of 30 days.
Can I configure different backup frequencies for different resource types?
Yes, the examples show hourlyFrequency of 6 hours for Compute instances and CloudSql, but 1 hour for disks. You can adjust frequency based on your needs.

Using a different cloud?

Explore storage guides for other cloud providers: