Configure AWS Data Lifecycle Manager Policies

The aws:dlm/lifecyclePolicy:LifecyclePolicy resource, part of the Pulumi AWS provider, defines Data Lifecycle Manager policies that automate EBS snapshot creation, retention, and cross-region replication. This guide focuses on four capabilities: schedule-based automation, cross-region disaster recovery, event-based snapshot handling, and application-consistent Windows backups.

DLM policies require IAM execution roles with DLM trust relationships and may reference KMS keys, target tags, or CloudWatch Events. The examples are intentionally small. Combine them with your own IAM roles, volume tags, and encryption keys.

Create daily EBS volume snapshots with retention

Most snapshot automation begins with a schedule that creates daily backups of tagged volumes and retains them for a fixed period.

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

const assumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["dlm.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const dlmLifecycleRole = new aws.iam.Role("dlm_lifecycle_role", {
    name: "dlm-lifecycle-role",
    assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json),
});
const dlmLifecycle = aws.iam.getPolicyDocument({
    statements: [
        {
            effect: "Allow",
            actions: [
                "ec2:CreateSnapshot",
                "ec2:CreateSnapshots",
                "ec2:DeleteSnapshot",
                "ec2:DescribeInstances",
                "ec2:DescribeVolumes",
                "ec2:DescribeSnapshots",
            ],
            resources: ["*"],
        },
        {
            effect: "Allow",
            actions: ["ec2:CreateTags"],
            resources: ["arn:aws:ec2:*::snapshot/*"],
        },
    ],
});
const dlmLifecycleRolePolicy = new aws.iam.RolePolicy("dlm_lifecycle", {
    name: "dlm-lifecycle-policy",
    role: dlmLifecycleRole.id,
    policy: dlmLifecycle.then(dlmLifecycle => dlmLifecycle.json),
});
const example = new aws.dlm.LifecyclePolicy("example", {
    description: "example DLM lifecycle policy",
    executionRoleArn: dlmLifecycleRole.arn,
    state: "ENABLED",
    policyDetails: {
        resourceTypes: ["VOLUME"],
        schedules: [{
            name: "2 weeks of daily snapshots",
            createRule: {
                interval: 24,
                intervalUnit: "HOURS",
                times: "23:45",
            },
            retainRule: {
                count: 14,
            },
            tagsToAdd: {
                SnapshotCreator: "DLM",
            },
            copyTags: false,
        }],
        targetTags: {
            Snapshot: "true",
        },
    },
});
import pulumi
import pulumi_aws as aws

assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["dlm.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
dlm_lifecycle_role = aws.iam.Role("dlm_lifecycle_role",
    name="dlm-lifecycle-role",
    assume_role_policy=assume_role.json)
dlm_lifecycle = aws.iam.get_policy_document(statements=[
    {
        "effect": "Allow",
        "actions": [
            "ec2:CreateSnapshot",
            "ec2:CreateSnapshots",
            "ec2:DeleteSnapshot",
            "ec2:DescribeInstances",
            "ec2:DescribeVolumes",
            "ec2:DescribeSnapshots",
        ],
        "resources": ["*"],
    },
    {
        "effect": "Allow",
        "actions": ["ec2:CreateTags"],
        "resources": ["arn:aws:ec2:*::snapshot/*"],
    },
])
dlm_lifecycle_role_policy = aws.iam.RolePolicy("dlm_lifecycle",
    name="dlm-lifecycle-policy",
    role=dlm_lifecycle_role.id,
    policy=dlm_lifecycle.json)
example = aws.dlm.LifecyclePolicy("example",
    description="example DLM lifecycle policy",
    execution_role_arn=dlm_lifecycle_role.arn,
    state="ENABLED",
    policy_details={
        "resource_types": ["VOLUME"],
        "schedules": [{
            "name": "2 weeks of daily snapshots",
            "create_rule": {
                "interval": 24,
                "interval_unit": "HOURS",
                "times": "23:45",
            },
            "retain_rule": {
                "count": 14,
            },
            "tags_to_add": {
                "SnapshotCreator": "DLM",
            },
            "copy_tags": False,
        }],
        "target_tags": {
            "Snapshot": "true",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		assumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"dlm.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		dlmLifecycleRole, err := iam.NewRole(ctx, "dlm_lifecycle_role", &iam.RoleArgs{
			Name:             pulumi.String("dlm-lifecycle-role"),
			AssumeRolePolicy: pulumi.String(assumeRole.Json),
		})
		if err != nil {
			return err
		}
		dlmLifecycle, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Actions: []string{
						"ec2:CreateSnapshot",
						"ec2:CreateSnapshots",
						"ec2:DeleteSnapshot",
						"ec2:DescribeInstances",
						"ec2:DescribeVolumes",
						"ec2:DescribeSnapshots",
					},
					Resources: []string{
						"*",
					},
				},
				{
					Effect: pulumi.StringRef("Allow"),
					Actions: []string{
						"ec2:CreateTags",
					},
					Resources: []string{
						"arn:aws:ec2:*::snapshot/*",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicy(ctx, "dlm_lifecycle", &iam.RolePolicyArgs{
			Name:   pulumi.String("dlm-lifecycle-policy"),
			Role:   dlmLifecycleRole.ID(),
			Policy: pulumi.String(dlmLifecycle.Json),
		})
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("example DLM lifecycle policy"),
			ExecutionRoleArn: dlmLifecycleRole.Arn,
			State:            pulumi.String("ENABLED"),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				ResourceTypes: pulumi.StringArray{
					pulumi.String("VOLUME"),
				},
				Schedules: dlm.LifecyclePolicyPolicyDetailsScheduleArray{
					&dlm.LifecyclePolicyPolicyDetailsScheduleArgs{
						Name: pulumi.String("2 weeks of daily snapshots"),
						CreateRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs{
							Interval:     pulumi.Int(24),
							IntervalUnit: pulumi.String("HOURS"),
							Times:        pulumi.String("23:45"),
						},
						RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs{
							Count: pulumi.Int(14),
						},
						TagsToAdd: pulumi.StringMap{
							"SnapshotCreator": pulumi.String("DLM"),
						},
						CopyTags: pulumi.Bool(false),
					},
				},
				TargetTags: pulumi.StringMap{
					"Snapshot": pulumi.String("true"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var assumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "dlm.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var dlmLifecycleRole = new Aws.Iam.Role("dlm_lifecycle_role", new()
    {
        Name = "dlm-lifecycle-role",
        AssumeRolePolicy = assumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var dlmLifecycle = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ec2:CreateSnapshot",
                    "ec2:CreateSnapshots",
                    "ec2:DeleteSnapshot",
                    "ec2:DescribeInstances",
                    "ec2:DescribeVolumes",
                    "ec2:DescribeSnapshots",
                },
                Resources = new[]
                {
                    "*",
                },
            },
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ec2:CreateTags",
                },
                Resources = new[]
                {
                    "arn:aws:ec2:*::snapshot/*",
                },
            },
        },
    });

    var dlmLifecycleRolePolicy = new Aws.Iam.RolePolicy("dlm_lifecycle", new()
    {
        Name = "dlm-lifecycle-policy",
        Role = dlmLifecycleRole.Id,
        Policy = dlmLifecycle.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var example = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "example DLM lifecycle policy",
        ExecutionRoleArn = dlmLifecycleRole.Arn,
        State = "ENABLED",
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            ResourceTypes = new[]
            {
                "VOLUME",
            },
            Schedules = new[]
            {
                new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleArgs
                {
                    Name = "2 weeks of daily snapshots",
                    CreateRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs
                    {
                        Interval = 24,
                        IntervalUnit = "HOURS",
                        Times = "23:45",
                    },
                    RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs
                    {
                        Count = 14,
                    },
                    TagsToAdd = 
                    {
                        { "SnapshotCreator", "DLM" },
                    },
                    CopyTags = false,
                },
            },
            TargetTags = 
            {
                { "Snapshot", "true" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.iam.RolePolicy;
import com.pulumi.aws.iam.RolePolicyArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var assumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("dlm.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var dlmLifecycleRole = new Role("dlmLifecycleRole", RoleArgs.builder()
            .name("dlm-lifecycle-role")
            .assumeRolePolicy(assumeRole.json())
            .build());

        final var dlmLifecycle = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(            
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions(                    
                        "ec2:CreateSnapshot",
                        "ec2:CreateSnapshots",
                        "ec2:DeleteSnapshot",
                        "ec2:DescribeInstances",
                        "ec2:DescribeVolumes",
                        "ec2:DescribeSnapshots")
                    .resources("*")
                    .build(),
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("ec2:CreateTags")
                    .resources("arn:aws:ec2:*::snapshot/*")
                    .build())
            .build());

        var dlmLifecycleRolePolicy = new RolePolicy("dlmLifecycleRolePolicy", RolePolicyArgs.builder()
            .name("dlm-lifecycle-policy")
            .role(dlmLifecycleRole.id())
            .policy(dlmLifecycle.json())
            .build());

        var example = new LifecyclePolicy("example", LifecyclePolicyArgs.builder()
            .description("example DLM lifecycle policy")
            .executionRoleArn(dlmLifecycleRole.arn())
            .state("ENABLED")
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .resourceTypes("VOLUME")
                .schedules(LifecyclePolicyPolicyDetailsScheduleArgs.builder()
                    .name("2 weeks of daily snapshots")
                    .createRule(LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs.builder()
                        .interval(24)
                        .intervalUnit("HOURS")
                        .times("23:45")
                        .build())
                    .retainRule(LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs.builder()
                        .count(14)
                        .build())
                    .tagsToAdd(Map.of("SnapshotCreator", "DLM"))
                    .copyTags(false)
                    .build())
                .targetTags(Map.of("Snapshot", "true"))
                .build())
            .build());

    }
}
resources:
  dlmLifecycleRole:
    type: aws:iam:Role
    name: dlm_lifecycle_role
    properties:
      name: dlm-lifecycle-role
      assumeRolePolicy: ${assumeRole.json}
  dlmLifecycleRolePolicy:
    type: aws:iam:RolePolicy
    name: dlm_lifecycle
    properties:
      name: dlm-lifecycle-policy
      role: ${dlmLifecycleRole.id}
      policy: ${dlmLifecycle.json}
  example:
    type: aws:dlm:LifecyclePolicy
    properties:
      description: example DLM lifecycle policy
      executionRoleArn: ${dlmLifecycleRole.arn}
      state: ENABLED
      policyDetails:
        resourceTypes:
          - VOLUME
        schedules:
          - name: 2 weeks of daily snapshots
            createRule:
              interval: 24
              intervalUnit: HOURS
              times: 23:45
            retainRule:
              count: 14
            tagsToAdd:
              SnapshotCreator: DLM
            copyTags: false
        targetTags:
          Snapshot: 'true'
variables:
  assumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - dlm.amazonaws.com
            actions:
              - sts:AssumeRole
  dlmLifecycle:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            actions:
              - ec2:CreateSnapshot
              - ec2:CreateSnapshots
              - ec2:DeleteSnapshot
              - ec2:DescribeInstances
              - ec2:DescribeVolumes
              - ec2:DescribeSnapshots
            resources:
              - '*'
          - effect: Allow
            actions:
              - ec2:CreateTags
            resources:
              - arn:aws:ec2:*::snapshot/*

The schedules array defines when snapshots are created and how long they’re kept. The createRule sets the backup frequency (every 24 hours at 23:45), while retainRule keeps 14 snapshots before deleting older ones. DLM only backs up volumes matching the targetTags criteria (Snapshot=true in this case). The executionRoleArn grants DLM permissions to create and manage snapshots.

Use simplified default policies for volume backups

AWS provides simplified default policies that apply standard backup schedules to all volumes without requiring detailed schedule configuration.

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

const example = new aws.dlm.LifecyclePolicy("example", {
    description: "tf-acc-basic",
    executionRoleArn: exampleAwsIamRole.arn,
    defaultPolicy: "VOLUME",
    policyDetails: {
        createInterval: 5,
        resourceType: "VOLUME",
        policyLanguage: "SIMPLIFIED",
        exclusions: {
            excludeBootVolumes: false,
            excludeTags: {
                test: "exclude",
            },
            excludeVolumeTypes: ["gp2"],
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.dlm.LifecyclePolicy("example",
    description="tf-acc-basic",
    execution_role_arn=example_aws_iam_role["arn"],
    default_policy="VOLUME",
    policy_details={
        "create_interval": 5,
        "resource_type": "VOLUME",
        "policy_language": "SIMPLIFIED",
        "exclusions": {
            "exclude_boot_volumes": False,
            "exclude_tags": {
                "test": "exclude",
            },
            "exclude_volume_types": ["gp2"],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("tf-acc-basic"),
			ExecutionRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			DefaultPolicy:    pulumi.String("VOLUME"),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				CreateInterval: pulumi.Int(5),
				ResourceType:   pulumi.String("VOLUME"),
				PolicyLanguage: pulumi.String("SIMPLIFIED"),
				Exclusions: &dlm.LifecyclePolicyPolicyDetailsExclusionsArgs{
					ExcludeBootVolumes: pulumi.Bool(false),
					ExcludeTags: pulumi.StringMap{
						"test": pulumi.String("exclude"),
					},
					ExcludeVolumeTypes: pulumi.StringArray{
						pulumi.String("gp2"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "tf-acc-basic",
        ExecutionRoleArn = exampleAwsIamRole.Arn,
        DefaultPolicy = "VOLUME",
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            CreateInterval = 5,
            ResourceType = "VOLUME",
            PolicyLanguage = "SIMPLIFIED",
            Exclusions = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsExclusionsArgs
            {
                ExcludeBootVolumes = false,
                ExcludeTags = 
                {
                    { "test", "exclude" },
                },
                ExcludeVolumeTypes = new[]
                {
                    "gp2",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsExclusionsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new LifecyclePolicy("example", LifecyclePolicyArgs.builder()
            .description("tf-acc-basic")
            .executionRoleArn(exampleAwsIamRole.arn())
            .defaultPolicy("VOLUME")
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .createInterval(5)
                .resourceType("VOLUME")
                .policyLanguage("SIMPLIFIED")
                .exclusions(LifecyclePolicyPolicyDetailsExclusionsArgs.builder()
                    .excludeBootVolumes(false)
                    .excludeTags(Map.of("test", "exclude"))
                    .excludeVolumeTypes("gp2")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:dlm:LifecyclePolicy
    properties:
      description: tf-acc-basic
      executionRoleArn: ${exampleAwsIamRole.arn}
      defaultPolicy: VOLUME
      policyDetails:
        createInterval: 5
        resourceType: VOLUME
        policyLanguage: SIMPLIFIED
        exclusions:
          excludeBootVolumes: false
          excludeTags:
            test: exclude
          excludeVolumeTypes:
            - gp2

The defaultPolicy property enables simplified mode, which uses AWS-managed schedules instead of custom createRule blocks. The createInterval sets how often snapshots are created (every 5 hours here). The exclusions block filters which volumes to skip: you can exclude boot volumes, specific volume types (like gp2), or volumes with certain tags.

Copy snapshots to another region for disaster recovery

Organizations with disaster recovery requirements replicate snapshots to a secondary region, often with separate retention policies and encryption keys.

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

// ...other configuration...
const current = aws.getCallerIdentity({});
const key = current.then(current => aws.iam.getPolicyDocument({
    statements: [{
        sid: "Enable IAM User Permissions",
        effect: "Allow",
        principals: [{
            type: "AWS",
            identifiers: [`arn:aws:iam::${current.accountId}:root`],
        }],
        actions: ["kms:*"],
        resources: ["*"],
    }],
}));
const dlmCrossRegionCopyCmk = new aws.kms.Key("dlm_cross_region_copy_cmk", {
    description: "Example Alternate Region KMS Key",
    policy: key.then(key => key.json),
});
const example = new aws.dlm.LifecyclePolicy("example", {
    description: "example DLM lifecycle policy",
    executionRoleArn: dlmLifecycleRole.arn,
    state: "ENABLED",
    policyDetails: {
        resourceTypes: ["VOLUME"],
        schedules: [{
            name: "2 weeks of daily snapshots",
            createRule: {
                interval: 24,
                intervalUnit: "HOURS",
                times: "23:45",
            },
            retainRule: {
                count: 14,
            },
            tagsToAdd: {
                SnapshotCreator: "DLM",
            },
            copyTags: false,
            crossRegionCopyRules: [{
                target: "us-west-2",
                encrypted: true,
                cmkArn: dlmCrossRegionCopyCmk.arn,
                copyTags: true,
                retainRule: {
                    interval: 30,
                    intervalUnit: "DAYS",
                },
            }],
        }],
        targetTags: {
            Snapshot: "true",
        },
    },
});
import pulumi
import pulumi_aws as aws

# ...other configuration...
current = aws.get_caller_identity()
key = aws.iam.get_policy_document(statements=[{
    "sid": "Enable IAM User Permissions",
    "effect": "Allow",
    "principals": [{
        "type": "AWS",
        "identifiers": [f"arn:aws:iam::{current.account_id}:root"],
    }],
    "actions": ["kms:*"],
    "resources": ["*"],
}])
dlm_cross_region_copy_cmk = aws.kms.Key("dlm_cross_region_copy_cmk",
    description="Example Alternate Region KMS Key",
    policy=key.json)
example = aws.dlm.LifecyclePolicy("example",
    description="example DLM lifecycle policy",
    execution_role_arn=dlm_lifecycle_role["arn"],
    state="ENABLED",
    policy_details={
        "resource_types": ["VOLUME"],
        "schedules": [{
            "name": "2 weeks of daily snapshots",
            "create_rule": {
                "interval": 24,
                "interval_unit": "HOURS",
                "times": "23:45",
            },
            "retain_rule": {
                "count": 14,
            },
            "tags_to_add": {
                "SnapshotCreator": "DLM",
            },
            "copy_tags": False,
            "cross_region_copy_rules": [{
                "target": "us-west-2",
                "encrypted": True,
                "cmk_arn": dlm_cross_region_copy_cmk.arn,
                "copy_tags": True,
                "retain_rule": {
                    "interval": 30,
                    "interval_unit": "DAYS",
                },
            }],
        }],
        "target_tags": {
            "Snapshot": "true",
        },
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// ...other configuration...
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		key, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Sid:    pulumi.StringRef("Enable IAM User Permissions"),
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "AWS",
							Identifiers: []string{
								fmt.Sprintf("arn:aws:iam::%v:root", current.AccountId),
							},
						},
					},
					Actions: []string{
						"kms:*",
					},
					Resources: []string{
						"*",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		dlmCrossRegionCopyCmk, err := kms.NewKey(ctx, "dlm_cross_region_copy_cmk", &kms.KeyArgs{
			Description: pulumi.String("Example Alternate Region KMS Key"),
			Policy:      pulumi.String(key.Json),
		})
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("example DLM lifecycle policy"),
			ExecutionRoleArn: pulumi.Any(dlmLifecycleRole.Arn),
			State:            pulumi.String("ENABLED"),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				ResourceTypes: pulumi.StringArray{
					pulumi.String("VOLUME"),
				},
				Schedules: dlm.LifecyclePolicyPolicyDetailsScheduleArray{
					&dlm.LifecyclePolicyPolicyDetailsScheduleArgs{
						Name: pulumi.String("2 weeks of daily snapshots"),
						CreateRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs{
							Interval:     pulumi.Int(24),
							IntervalUnit: pulumi.String("HOURS"),
							Times:        pulumi.String("23:45"),
						},
						RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs{
							Count: pulumi.Int(14),
						},
						TagsToAdd: pulumi.StringMap{
							"SnapshotCreator": pulumi.String("DLM"),
						},
						CopyTags: pulumi.Bool(false),
						CrossRegionCopyRules: dlm.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArray{
							&dlm.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArgs{
								Target:    pulumi.String("us-west-2"),
								Encrypted: pulumi.Bool(true),
								CmkArn:    dlmCrossRegionCopyCmk.Arn,
								CopyTags:  pulumi.Bool(true),
								RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleRetainRuleArgs{
									Interval:     pulumi.Int(30),
									IntervalUnit: pulumi.String("DAYS"),
								},
							},
						},
					},
				},
				TargetTags: pulumi.StringMap{
					"Snapshot": pulumi.String("true"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    // ...other configuration...
    var current = Aws.GetCallerIdentity.Invoke();

    var key = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Sid = "Enable IAM User Permissions",
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "AWS",
                        Identifiers = new[]
                        {
                            $"arn:aws:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root",
                        },
                    },
                },
                Actions = new[]
                {
                    "kms:*",
                },
                Resources = new[]
                {
                    "*",
                },
            },
        },
    });

    var dlmCrossRegionCopyCmk = new Aws.Kms.Key("dlm_cross_region_copy_cmk", new()
    {
        Description = "Example Alternate Region KMS Key",
        Policy = key.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var example = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "example DLM lifecycle policy",
        ExecutionRoleArn = dlmLifecycleRole.Arn,
        State = "ENABLED",
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            ResourceTypes = new[]
            {
                "VOLUME",
            },
            Schedules = new[]
            {
                new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleArgs
                {
                    Name = "2 weeks of daily snapshots",
                    CreateRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs
                    {
                        Interval = 24,
                        IntervalUnit = "HOURS",
                        Times = "23:45",
                    },
                    RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs
                    {
                        Count = 14,
                    },
                    TagsToAdd = 
                    {
                        { "SnapshotCreator", "DLM" },
                    },
                    CopyTags = false,
                    CrossRegionCopyRules = new[]
                    {
                        new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArgs
                        {
                            Target = "us-west-2",
                            Encrypted = true,
                            CmkArn = dlmCrossRegionCopyCmk.Arn,
                            CopyTags = true,
                            RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleRetainRuleArgs
                            {
                                Interval = 30,
                                IntervalUnit = "DAYS",
                            },
                        },
                    },
                },
            },
            TargetTags = 
            {
                { "Snapshot", "true" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
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) {
        // ...other configuration...
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        final var key = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .sid("Enable IAM User Permissions")
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("AWS")
                    .identifiers(String.format("arn:aws:iam::%s:root", current.accountId()))
                    .build())
                .actions("kms:*")
                .resources("*")
                .build())
            .build());

        var dlmCrossRegionCopyCmk = new Key("dlmCrossRegionCopyCmk", KeyArgs.builder()
            .description("Example Alternate Region KMS Key")
            .policy(key.json())
            .build());

        var example = new LifecyclePolicy("example", LifecyclePolicyArgs.builder()
            .description("example DLM lifecycle policy")
            .executionRoleArn(dlmLifecycleRole.arn())
            .state("ENABLED")
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .resourceTypes("VOLUME")
                .schedules(LifecyclePolicyPolicyDetailsScheduleArgs.builder()
                    .name("2 weeks of daily snapshots")
                    .createRule(LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs.builder()
                        .interval(24)
                        .intervalUnit("HOURS")
                        .times("23:45")
                        .build())
                    .retainRule(LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs.builder()
                        .count(14)
                        .build())
                    .tagsToAdd(Map.of("SnapshotCreator", "DLM"))
                    .copyTags(false)
                    .crossRegionCopyRules(LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleArgs.builder()
                        .target("us-west-2")
                        .encrypted(true)
                        .cmkArn(dlmCrossRegionCopyCmk.arn())
                        .copyTags(true)
                        .retainRule(LifecyclePolicyPolicyDetailsScheduleCrossRegionCopyRuleRetainRuleArgs.builder()
                            .interval(30)
                            .intervalUnit("DAYS")
                            .build())
                        .build())
                    .build())
                .targetTags(Map.of("Snapshot", "true"))
                .build())
            .build());

    }
}
resources:
  dlmCrossRegionCopyCmk:
    type: aws:kms:Key
    name: dlm_cross_region_copy_cmk
    properties:
      description: Example Alternate Region KMS Key
      policy: ${key.json}
  example:
    type: aws:dlm:LifecyclePolicy
    properties:
      description: example DLM lifecycle policy
      executionRoleArn: ${dlmLifecycleRole.arn}
      state: ENABLED
      policyDetails:
        resourceTypes:
          - VOLUME
        schedules:
          - name: 2 weeks of daily snapshots
            createRule:
              interval: 24
              intervalUnit: HOURS
              times: 23:45
            retainRule:
              count: 14
            tagsToAdd:
              SnapshotCreator: DLM
            copyTags: false
            crossRegionCopyRules:
              - target: us-west-2
                encrypted: true
                cmkArn: ${dlmCrossRegionCopyCmk.arn}
                copyTags: true
                retainRule:
                  interval: 30
                  intervalUnit: DAYS
        targetTags:
          Snapshot: 'true'
variables:
  # ...other configuration...
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}
  key:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - sid: Enable IAM User Permissions
            effect: Allow
            principals:
              - type: AWS
                identifiers:
                  - arn:aws:iam::${current.accountId}:root
            actions:
              - kms:*
            resources:
              - '*'

The crossRegionCopyRules array defines replication targets. Each rule specifies a target region (us-west-2), whether to encrypt copies, and which KMS key to use (cmkArn). The nested retainRule controls how long copies are kept in the target region (30 days), which can differ from the source region’s retention. This extends the basic schedule with geographic redundancy.

Respond to snapshot sharing events automatically

Event-based policies trigger actions when specific CloudWatch Events occur, such as when snapshots are shared with your account.

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

const current = aws.getCallerIdentity({});
const exampleLifecyclePolicy = new aws.dlm.LifecyclePolicy("example", {
    description: "tf-acc-basic",
    executionRoleArn: exampleAwsIamRole.arn,
    policyDetails: {
        policyType: "EVENT_BASED_POLICY",
        action: {
            name: "tf-acc-basic",
            crossRegionCopies: [{
                encryptionConfiguration: {},
                retainRule: {
                    interval: 15,
                    intervalUnit: "MONTHS",
                },
                target: "us-east-1",
            }],
        },
        eventSource: {
            type: "MANAGED_CWE",
            parameters: {
                descriptionRegex: "^.*Created for policy: policy-1234567890abcdef0.*$",
                eventType: "shareSnapshot",
                snapshotOwners: [current.then(current => current.accountId)],
            },
        },
    },
});
const example = aws.iam.getPolicy({
    name: "AWSDataLifecycleManagerServiceRole",
});
const exampleRolePolicyAttachment = new aws.iam.RolePolicyAttachment("example", {
    role: exampleAwsIamRole.id,
    policyArn: example.then(example => example.arn),
});
import pulumi
import pulumi_aws as aws

current = aws.get_caller_identity()
example_lifecycle_policy = aws.dlm.LifecyclePolicy("example",
    description="tf-acc-basic",
    execution_role_arn=example_aws_iam_role["arn"],
    policy_details={
        "policy_type": "EVENT_BASED_POLICY",
        "action": {
            "name": "tf-acc-basic",
            "cross_region_copies": [{
                "encryption_configuration": {},
                "retain_rule": {
                    "interval": 15,
                    "interval_unit": "MONTHS",
                },
                "target": "us-east-1",
            }],
        },
        "event_source": {
            "type": "MANAGED_CWE",
            "parameters": {
                "description_regex": "^.*Created for policy: policy-1234567890abcdef0.*$",
                "event_type": "shareSnapshot",
                "snapshot_owners": [current.account_id],
            },
        },
    })
example = aws.iam.get_policy(name="AWSDataLifecycleManagerServiceRole")
example_role_policy_attachment = aws.iam.RolePolicyAttachment("example",
    role=example_aws_iam_role["id"],
    policy_arn=example.arn)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("tf-acc-basic"),
			ExecutionRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				PolicyType: pulumi.String("EVENT_BASED_POLICY"),
				Action: &dlm.LifecyclePolicyPolicyDetailsActionArgs{
					Name: pulumi.String("tf-acc-basic"),
					CrossRegionCopies: dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyArray{
						&dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyArgs{
							EncryptionConfiguration: &dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyEncryptionConfigurationArgs{},
							RetainRule: &dlm.LifecyclePolicyPolicyDetailsActionCrossRegionCopyRetainRuleArgs{
								Interval:     pulumi.Int(15),
								IntervalUnit: pulumi.String("MONTHS"),
							},
							Target: pulumi.String("us-east-1"),
						},
					},
				},
				EventSource: &dlm.LifecyclePolicyPolicyDetailsEventSourceArgs{
					Type: pulumi.String("MANAGED_CWE"),
					Parameters: &dlm.LifecyclePolicyPolicyDetailsEventSourceParametersArgs{
						DescriptionRegex: pulumi.String("^.*Created for policy: policy-1234567890abcdef0.*$"),
						EventType:        pulumi.String("shareSnapshot"),
						SnapshotOwners: pulumi.StringArray{
							pulumi.String(current.AccountId),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		example, err := iam.LookupPolicy(ctx, &iam.LookupPolicyArgs{
			Name: pulumi.StringRef("AWSDataLifecycleManagerServiceRole"),
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "example", &iam.RolePolicyAttachmentArgs{
			Role:      pulumi.Any(exampleAwsIamRole.Id),
			PolicyArn: pulumi.String(example.Arn),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var exampleLifecyclePolicy = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "tf-acc-basic",
        ExecutionRoleArn = exampleAwsIamRole.Arn,
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            PolicyType = "EVENT_BASED_POLICY",
            Action = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsActionArgs
            {
                Name = "tf-acc-basic",
                CrossRegionCopies = new[]
                {
                    new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsActionCrossRegionCopyArgs
                    {
                        EncryptionConfiguration = null,
                        RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsActionCrossRegionCopyRetainRuleArgs
                        {
                            Interval = 15,
                            IntervalUnit = "MONTHS",
                        },
                        Target = "us-east-1",
                    },
                },
            },
            EventSource = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsEventSourceArgs
            {
                Type = "MANAGED_CWE",
                Parameters = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsEventSourceParametersArgs
                {
                    DescriptionRegex = "^.*Created for policy: policy-1234567890abcdef0.*$",
                    EventType = "shareSnapshot",
                    SnapshotOwners = new[]
                    {
                        current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId),
                    },
                },
            },
        },
    });

    var example = Aws.Iam.GetPolicy.Invoke(new()
    {
        Name = "AWSDataLifecycleManagerServiceRole",
    });

    var exampleRolePolicyAttachment = new Aws.Iam.RolePolicyAttachment("example", new()
    {
        Role = exampleAwsIamRole.Id,
        PolicyArn = example.Apply(getPolicyResult => getPolicyResult.Arn),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsActionArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsEventSourceArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsEventSourceParametersArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        var exampleLifecyclePolicy = new LifecyclePolicy("exampleLifecyclePolicy", LifecyclePolicyArgs.builder()
            .description("tf-acc-basic")
            .executionRoleArn(exampleAwsIamRole.arn())
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .policyType("EVENT_BASED_POLICY")
                .action(LifecyclePolicyPolicyDetailsActionArgs.builder()
                    .name("tf-acc-basic")
                    .crossRegionCopies(LifecyclePolicyPolicyDetailsActionCrossRegionCopyArgs.builder()
                        .encryptionConfiguration(LifecyclePolicyPolicyDetailsActionCrossRegionCopyEncryptionConfigurationArgs.builder()
                            .build())
                        .retainRule(LifecyclePolicyPolicyDetailsActionCrossRegionCopyRetainRuleArgs.builder()
                            .interval(15)
                            .intervalUnit("MONTHS")
                            .build())
                        .target("us-east-1")
                        .build())
                    .build())
                .eventSource(LifecyclePolicyPolicyDetailsEventSourceArgs.builder()
                    .type("MANAGED_CWE")
                    .parameters(LifecyclePolicyPolicyDetailsEventSourceParametersArgs.builder()
                        .descriptionRegex("^.*Created for policy: policy-1234567890abcdef0.*$")
                        .eventType("shareSnapshot")
                        .snapshotOwners(current.accountId())
                        .build())
                    .build())
                .build())
            .build());

        final var example = IamFunctions.getPolicy(GetPolicyArgs.builder()
            .name("AWSDataLifecycleManagerServiceRole")
            .build());

        var exampleRolePolicyAttachment = new RolePolicyAttachment("exampleRolePolicyAttachment", RolePolicyAttachmentArgs.builder()
            .role(exampleAwsIamRole.id())
            .policyArn(example.arn())
            .build());

    }
}
resources:
  exampleLifecyclePolicy:
    type: aws:dlm:LifecyclePolicy
    name: example
    properties:
      description: tf-acc-basic
      executionRoleArn: ${exampleAwsIamRole.arn}
      policyDetails:
        policyType: EVENT_BASED_POLICY
        action:
          name: tf-acc-basic
          crossRegionCopies:
            - encryptionConfiguration: {}
              retainRule:
                interval: 15
                intervalUnit: MONTHS
              target: us-east-1
        eventSource:
          type: MANAGED_CWE
          parameters:
            descriptionRegex: '^.*Created for policy: policy-1234567890abcdef0.*$'
            eventType: shareSnapshot
            snapshotOwners:
              - ${current.accountId}
  exampleRolePolicyAttachment:
    type: aws:iam:RolePolicyAttachment
    name: example
    properties:
      role: ${exampleAwsIamRole.id}
      policyArn: ${example.arn}
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}
  example:
    fn::invoke:
      function: aws:iam:getPolicy
      arguments:
        name: AWSDataLifecycleManagerServiceRole

The policyType switches from schedule-based to event-based operation. The eventSource block defines which CloudWatch Events to monitor: here, it watches for shareSnapshot events from specific accounts (snapshotOwners). When a matching event occurs, the action block executes, copying the shared snapshot to us-east-1 with 15-month retention. This requires the AWSDataLifecycleManagerServiceRole managed policy attached to your execution role.

Run application-consistent backups with VSS

Windows workloads often require application-consistent snapshots using Volume Shadow Copy Service to ensure database integrity during backup.

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

const test = aws.iam.getPolicy({
    name: "AWSDataLifecycleManagerSSMFullAccess",
});
const example = new aws.iam.RolePolicyAttachment("example", {
    role: testAwsIamRole.id,
    policyArn: exampleAwsIamPolicy.arn,
});
const exampleLifecyclePolicy = new aws.dlm.LifecyclePolicy("example", {
    description: "tf-acc-basic",
    executionRoleArn: exampleAwsIamRole.arn,
    policyDetails: {
        resourceTypes: ["INSTANCE"],
        schedules: [{
            name: "Windows VSS",
            createRule: {
                interval: 12,
                scripts: {
                    executeOperationOnScriptFailure: false,
                    executionHandler: "AWS_VSS_BACKUP",
                    maximumRetryCount: 2,
                },
            },
            retainRule: {
                count: 10,
            },
        }],
        targetTags: {
            tag1: "Windows",
        },
    },
});
import pulumi
import pulumi_aws as aws

test = aws.iam.get_policy(name="AWSDataLifecycleManagerSSMFullAccess")
example = aws.iam.RolePolicyAttachment("example",
    role=test_aws_iam_role["id"],
    policy_arn=example_aws_iam_policy["arn"])
example_lifecycle_policy = aws.dlm.LifecyclePolicy("example",
    description="tf-acc-basic",
    execution_role_arn=example_aws_iam_role["arn"],
    policy_details={
        "resource_types": ["INSTANCE"],
        "schedules": [{
            "name": "Windows VSS",
            "create_rule": {
                "interval": 12,
                "scripts": {
                    "execute_operation_on_script_failure": False,
                    "execution_handler": "AWS_VSS_BACKUP",
                    "maximum_retry_count": 2,
                },
            },
            "retain_rule": {
                "count": 10,
            },
        }],
        "target_tags": {
            "tag1": "Windows",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/dlm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := iam.LookupPolicy(ctx, &iam.LookupPolicyArgs{
			Name: pulumi.StringRef("AWSDataLifecycleManagerSSMFullAccess"),
		}, nil)
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "example", &iam.RolePolicyAttachmentArgs{
			Role:      pulumi.Any(testAwsIamRole.Id),
			PolicyArn: pulumi.Any(exampleAwsIamPolicy.Arn),
		})
		if err != nil {
			return err
		}
		_, err = dlm.NewLifecyclePolicy(ctx, "example", &dlm.LifecyclePolicyArgs{
			Description:      pulumi.String("tf-acc-basic"),
			ExecutionRoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			PolicyDetails: &dlm.LifecyclePolicyPolicyDetailsArgs{
				ResourceTypes: pulumi.StringArray{
					pulumi.String("INSTANCE"),
				},
				Schedules: dlm.LifecyclePolicyPolicyDetailsScheduleArray{
					&dlm.LifecyclePolicyPolicyDetailsScheduleArgs{
						Name: pulumi.String("Windows VSS"),
						CreateRule: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs{
							Interval: pulumi.Int(12),
							Scripts: &dlm.LifecyclePolicyPolicyDetailsScheduleCreateRuleScriptsArgs{
								ExecuteOperationOnScriptFailure: pulumi.Bool(false),
								ExecutionHandler:                pulumi.String("AWS_VSS_BACKUP"),
								MaximumRetryCount:               pulumi.Int(2),
							},
						},
						RetainRule: &dlm.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs{
							Count: pulumi.Int(10),
						},
					},
				},
				TargetTags: pulumi.StringMap{
					"tag1": pulumi.String("Windows"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var test = Aws.Iam.GetPolicy.Invoke(new()
    {
        Name = "AWSDataLifecycleManagerSSMFullAccess",
    });

    var example = new Aws.Iam.RolePolicyAttachment("example", new()
    {
        Role = testAwsIamRole.Id,
        PolicyArn = exampleAwsIamPolicy.Arn,
    });

    var exampleLifecyclePolicy = new Aws.Dlm.LifecyclePolicy("example", new()
    {
        Description = "tf-acc-basic",
        ExecutionRoleArn = exampleAwsIamRole.Arn,
        PolicyDetails = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsArgs
        {
            ResourceTypes = new[]
            {
                "INSTANCE",
            },
            Schedules = new[]
            {
                new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleArgs
                {
                    Name = "Windows VSS",
                    CreateRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs
                    {
                        Interval = 12,
                        Scripts = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleCreateRuleScriptsArgs
                        {
                            ExecuteOperationOnScriptFailure = false,
                            ExecutionHandler = "AWS_VSS_BACKUP",
                            MaximumRetryCount = 2,
                        },
                    },
                    RetainRule = new Aws.Dlm.Inputs.LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs
                    {
                        Count = 10,
                    },
                },
            },
            TargetTags = 
            {
                { "tag1", "Windows" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import com.pulumi.aws.dlm.LifecyclePolicy;
import com.pulumi.aws.dlm.LifecyclePolicyArgs;
import com.pulumi.aws.dlm.inputs.LifecyclePolicyPolicyDetailsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var test = IamFunctions.getPolicy(GetPolicyArgs.builder()
            .name("AWSDataLifecycleManagerSSMFullAccess")
            .build());

        var example = new RolePolicyAttachment("example", RolePolicyAttachmentArgs.builder()
            .role(testAwsIamRole.id())
            .policyArn(exampleAwsIamPolicy.arn())
            .build());

        var exampleLifecyclePolicy = new LifecyclePolicy("exampleLifecyclePolicy", LifecyclePolicyArgs.builder()
            .description("tf-acc-basic")
            .executionRoleArn(exampleAwsIamRole.arn())
            .policyDetails(LifecyclePolicyPolicyDetailsArgs.builder()
                .resourceTypes("INSTANCE")
                .schedules(LifecyclePolicyPolicyDetailsScheduleArgs.builder()
                    .name("Windows VSS")
                    .createRule(LifecyclePolicyPolicyDetailsScheduleCreateRuleArgs.builder()
                        .interval(12)
                        .scripts(LifecyclePolicyPolicyDetailsScheduleCreateRuleScriptsArgs.builder()
                            .executeOperationOnScriptFailure(false)
                            .executionHandler("AWS_VSS_BACKUP")
                            .maximumRetryCount(2)
                            .build())
                        .build())
                    .retainRule(LifecyclePolicyPolicyDetailsScheduleRetainRuleArgs.builder()
                        .count(10)
                        .build())
                    .build())
                .targetTags(Map.of("tag1", "Windows"))
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:iam:RolePolicyAttachment
    properties:
      role: ${testAwsIamRole.id}
      policyArn: ${exampleAwsIamPolicy.arn}
  exampleLifecyclePolicy:
    type: aws:dlm:LifecyclePolicy
    name: example
    properties:
      description: tf-acc-basic
      executionRoleArn: ${exampleAwsIamRole.arn}
      policyDetails:
        resourceTypes:
          - INSTANCE
        schedules:
          - name: Windows VSS
            createRule:
              interval: 12
              scripts:
                executeOperationOnScriptFailure: false
                executionHandler: AWS_VSS_BACKUP
                maximumRetryCount: 2
            retainRule:
              count: 10
        targetTags:
          tag1: Windows
variables:
  test:
    fn::invoke:
      function: aws:iam:getPolicy
      arguments:
        name: AWSDataLifecycleManagerSSMFullAccess

The scripts block enables pre/post-snapshot hooks. The executionHandler property specifies AWS_VSS_BACKUP, which triggers Windows VSS before creating snapshots. The maximumRetryCount controls how many times DLM retries if VSS fails, and executeOperationOnScriptFailure determines whether to create snapshots even when VSS fails. This requires the AWSDataLifecycleManagerSSMFullAccess policy and only works with Windows instances that support VSS.

Beyond these examples

These snippets focus on specific lifecycle policy features: schedule-based and event-based policies, cross-region replication and encryption, and application-consistent snapshots with VSS. They’re intentionally minimal rather than full backup solutions.

The examples may reference pre-existing infrastructure such as IAM execution roles with DLM trust policy, KMS keys in target regions for encrypted copies, and EBS volumes or EC2 instances with target tags. They focus on configuring the policy rather than provisioning everything around it.

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

  • Fast snapshot restore configuration (fastRestoreRule)
  • Snapshot sharing across accounts (shareRules)
  • Archive tier lifecycle transitions
  • Variable schedule intervals and cron expressions

These omissions are intentional: the goal is to illustrate how each lifecycle policy feature is wired, not provide drop-in backup modules. See the DLM Lifecycle Policy resource reference for all available configuration options.

Let's configure AWS Data Lifecycle Manager Policies

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

IAM & Permissions
What IAM permissions does DLM need to create snapshots?
The IAM role must include EC2 permissions: ec2:CreateSnapshot, ec2:CreateSnapshots, ec2:DeleteSnapshot, ec2:DescribeInstances, ec2:DescribeVolumes, ec2:DescribeSnapshots, and ec2:CreateTags for snapshot resources. The role’s trust policy must allow dlm.amazonaws.com to assume it.
What additional IAM permissions do I need for event-based policies?
Attach the AWS managed policy AWSDataLifecycleManagerServiceRole to your IAM role for event-based policies.
What IAM permissions do I need for pre/post scripts?
Attach the AWS managed policy AWSDataLifecycleManagerSSMFullAccess to enable application-consistent snapshots with scripts.
Policy Configuration
How do I target specific resources for snapshots?
Use targetTags in policyDetails to identify resources by their tags. DLM will create snapshots for all resources matching those tags.
Can I exclude certain volumes from snapshots?
Yes, use exclusions in policyDetails to exclude boot volumes (excludeBootVolumes), specific tags (excludeTags), or volume types like gp2 (excludeVolumeTypes).
What's the difference between schedule-based and event-based policies?
Schedule-based policies create snapshots on a time-based schedule using createRule with interval and times. Event-based policies (policyType: EVENT_BASED_POLICY) trigger on CloudWatch Events like snapshot sharing, using eventSource configuration.
What's a default policy and when should I use it?
A default policy (defaultPolicy: VOLUME or INSTANCE) uses simplified configuration (policyLanguage: SIMPLIFIED) with automatic scheduling. Use it for straightforward snapshot policies with exclusion rules instead of complex schedules.
How do I temporarily disable a lifecycle policy?
Set state to DISABLED. Policies default to ENABLED when created.
Cross-Region & Advanced Features
How do I set up cross-region snapshot copies?
Configure crossRegionCopyRules in your schedule with the target region, encryption settings (encrypted: true), and a KMS key ARN (cmkArn) in the target region. You can also specify separate retention rules for the copied snapshots.
How do I enable application-consistent snapshots for Windows instances?
Set resourceTypes to INSTANCE and configure scripts in createRule with executionHandler: AWS_VSS_BACKUP. Your IAM role must have the AWSDataLifecycleManagerSSMFullAccess policy attached.

Using a different cloud?

Explore storage guides for other cloud providers: