Configure Azure Storage Object Replication Policies

The azure-native:storage:ObjectReplicationPolicy resource, part of the Pulumi Azure Native provider, defines object replication policies that asynchronously copy blobs between a source storage account and a destination account. This guide focuses on three capabilities: destination-side policy creation, source-side configuration with Azure-generated IDs, and multi-rule policies for multiple container pairs.

Object replication requires two storage accounts with blob versioning and change feed enabled, plus existing containers in both accounts. The examples are intentionally small. Combine them with your own storage accounts and container infrastructure.

Create a policy on the destination account

Object replication setup begins on the destination account, where you define which containers receive replicated objects and what filtering rules apply.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const objectReplicationPolicy = new azure_native.storage.ObjectReplicationPolicy("objectReplicationPolicy", {
    accountName: "dst112",
    destinationAccount: "dst112",
    metrics: {
        enabled: true,
    },
    objectReplicationPolicyId: "default",
    resourceGroupName: "res7687",
    rules: [{
        destinationContainer: "dcont139",
        filters: {
            prefixMatch: [
                "blobA",
                "blobB",
            ],
        },
        sourceContainer: "scont139",
    }],
    sourceAccount: "src1122",
});
import pulumi
import pulumi_azure_native as azure_native

object_replication_policy = azure_native.storage.ObjectReplicationPolicy("objectReplicationPolicy",
    account_name="dst112",
    destination_account="dst112",
    metrics={
        "enabled": True,
    },
    object_replication_policy_id="default",
    resource_group_name="res7687",
    rules=[{
        "destination_container": "dcont139",
        "filters": {
            "prefix_match": [
                "blobA",
                "blobB",
            ],
        },
        "source_container": "scont139",
    }],
    source_account="src1122")
package main

import (
	storage "github.com/pulumi/pulumi-azure-native-sdk/storage/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storage.NewObjectReplicationPolicy(ctx, "objectReplicationPolicy", &storage.ObjectReplicationPolicyArgs{
			AccountName:        pulumi.String("dst112"),
			DestinationAccount: pulumi.String("dst112"),
			Metrics: &storage.ObjectReplicationPolicyPropertiesMetricsArgs{
				Enabled: pulumi.Bool(true),
			},
			ObjectReplicationPolicyId: pulumi.String("default"),
			ResourceGroupName:         pulumi.String("res7687"),
			Rules: storage.ObjectReplicationPolicyRuleArray{
				&storage.ObjectReplicationPolicyRuleArgs{
					DestinationContainer: pulumi.String("dcont139"),
					Filters: &storage.ObjectReplicationPolicyFilterArgs{
						PrefixMatch: pulumi.StringArray{
							pulumi.String("blobA"),
							pulumi.String("blobB"),
						},
					},
					SourceContainer: pulumi.String("scont139"),
				},
			},
			SourceAccount: pulumi.String("src1122"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var objectReplicationPolicy = new AzureNative.Storage.ObjectReplicationPolicy("objectReplicationPolicy", new()
    {
        AccountName = "dst112",
        DestinationAccount = "dst112",
        Metrics = new AzureNative.Storage.Inputs.ObjectReplicationPolicyPropertiesMetricsArgs
        {
            Enabled = true,
        },
        ObjectReplicationPolicyId = "default",
        ResourceGroupName = "res7687",
        Rules = new[]
        {
            new AzureNative.Storage.Inputs.ObjectReplicationPolicyRuleArgs
            {
                DestinationContainer = "dcont139",
                Filters = new AzureNative.Storage.Inputs.ObjectReplicationPolicyFilterArgs
                {
                    PrefixMatch = new[]
                    {
                        "blobA",
                        "blobB",
                    },
                },
                SourceContainer = "scont139",
            },
        },
        SourceAccount = "src1122",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.ObjectReplicationPolicy;
import com.pulumi.azurenative.storage.ObjectReplicationPolicyArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyPropertiesMetricsArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyRuleArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyFilterArgs;
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 objectReplicationPolicy = new ObjectReplicationPolicy("objectReplicationPolicy", ObjectReplicationPolicyArgs.builder()
            .accountName("dst112")
            .destinationAccount("dst112")
            .metrics(ObjectReplicationPolicyPropertiesMetricsArgs.builder()
                .enabled(true)
                .build())
            .objectReplicationPolicyId("default")
            .resourceGroupName("res7687")
            .rules(ObjectReplicationPolicyRuleArgs.builder()
                .destinationContainer("dcont139")
                .filters(ObjectReplicationPolicyFilterArgs.builder()
                    .prefixMatch(                    
                        "blobA",
                        "blobB")
                    .build())
                .sourceContainer("scont139")
                .build())
            .sourceAccount("src1122")
            .build());

    }
}
resources:
  objectReplicationPolicy:
    type: azure-native:storage:ObjectReplicationPolicy
    properties:
      accountName: dst112
      destinationAccount: dst112
      metrics:
        enabled: true
      objectReplicationPolicyId: default
      resourceGroupName: res7687
      rules:
        - destinationContainer: dcont139
          filters:
            prefixMatch:
              - blobA
              - blobB
          sourceContainer: scont139
      sourceAccount: src1122

The destinationAccount and sourceAccount properties identify the two storage accounts involved. Each rule in the rules array maps a sourceContainer to a destinationContainer. The filters property lets you replicate only blobs matching specific prefixes. Azure generates a policy ID and rule IDs when you create this resource; you’ll need these values for the source-side configuration.

Configure the source account with policy and rule IDs

After creating the destination policy, you configure the source account using the policy ID and rule IDs that Azure returned.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const objectReplicationPolicy = new azure_native.storage.ObjectReplicationPolicy("objectReplicationPolicy", {
    accountName: "src1122",
    destinationAccount: "dst112",
    metrics: {
        enabled: true,
    },
    objectReplicationPolicyId: "2a20bb73-5717-4635-985a-5d4cf777438f",
    resourceGroupName: "res7687",
    rules: [{
        destinationContainer: "dcont139",
        filters: {
            minCreationTime: "2020-02-19T16:05:00Z",
            prefixMatch: [
                "blobA",
                "blobB",
            ],
        },
        ruleId: "d5d18a48-8801-4554-aeaa-74faf65f5ef9",
        sourceContainer: "scont139",
    }],
    sourceAccount: "src1122",
});
import pulumi
import pulumi_azure_native as azure_native

object_replication_policy = azure_native.storage.ObjectReplicationPolicy("objectReplicationPolicy",
    account_name="src1122",
    destination_account="dst112",
    metrics={
        "enabled": True,
    },
    object_replication_policy_id="2a20bb73-5717-4635-985a-5d4cf777438f",
    resource_group_name="res7687",
    rules=[{
        "destination_container": "dcont139",
        "filters": {
            "min_creation_time": "2020-02-19T16:05:00Z",
            "prefix_match": [
                "blobA",
                "blobB",
            ],
        },
        "rule_id": "d5d18a48-8801-4554-aeaa-74faf65f5ef9",
        "source_container": "scont139",
    }],
    source_account="src1122")
package main

import (
	storage "github.com/pulumi/pulumi-azure-native-sdk/storage/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storage.NewObjectReplicationPolicy(ctx, "objectReplicationPolicy", &storage.ObjectReplicationPolicyArgs{
			AccountName:        pulumi.String("src1122"),
			DestinationAccount: pulumi.String("dst112"),
			Metrics: &storage.ObjectReplicationPolicyPropertiesMetricsArgs{
				Enabled: pulumi.Bool(true),
			},
			ObjectReplicationPolicyId: pulumi.String("2a20bb73-5717-4635-985a-5d4cf777438f"),
			ResourceGroupName:         pulumi.String("res7687"),
			Rules: storage.ObjectReplicationPolicyRuleArray{
				&storage.ObjectReplicationPolicyRuleArgs{
					DestinationContainer: pulumi.String("dcont139"),
					Filters: &storage.ObjectReplicationPolicyFilterArgs{
						MinCreationTime: pulumi.String("2020-02-19T16:05:00Z"),
						PrefixMatch: pulumi.StringArray{
							pulumi.String("blobA"),
							pulumi.String("blobB"),
						},
					},
					RuleId:          pulumi.String("d5d18a48-8801-4554-aeaa-74faf65f5ef9"),
					SourceContainer: pulumi.String("scont139"),
				},
			},
			SourceAccount: pulumi.String("src1122"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var objectReplicationPolicy = new AzureNative.Storage.ObjectReplicationPolicy("objectReplicationPolicy", new()
    {
        AccountName = "src1122",
        DestinationAccount = "dst112",
        Metrics = new AzureNative.Storage.Inputs.ObjectReplicationPolicyPropertiesMetricsArgs
        {
            Enabled = true,
        },
        ObjectReplicationPolicyId = "2a20bb73-5717-4635-985a-5d4cf777438f",
        ResourceGroupName = "res7687",
        Rules = new[]
        {
            new AzureNative.Storage.Inputs.ObjectReplicationPolicyRuleArgs
            {
                DestinationContainer = "dcont139",
                Filters = new AzureNative.Storage.Inputs.ObjectReplicationPolicyFilterArgs
                {
                    MinCreationTime = "2020-02-19T16:05:00Z",
                    PrefixMatch = new[]
                    {
                        "blobA",
                        "blobB",
                    },
                },
                RuleId = "d5d18a48-8801-4554-aeaa-74faf65f5ef9",
                SourceContainer = "scont139",
            },
        },
        SourceAccount = "src1122",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.ObjectReplicationPolicy;
import com.pulumi.azurenative.storage.ObjectReplicationPolicyArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyPropertiesMetricsArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyRuleArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyFilterArgs;
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 objectReplicationPolicy = new ObjectReplicationPolicy("objectReplicationPolicy", ObjectReplicationPolicyArgs.builder()
            .accountName("src1122")
            .destinationAccount("dst112")
            .metrics(ObjectReplicationPolicyPropertiesMetricsArgs.builder()
                .enabled(true)
                .build())
            .objectReplicationPolicyId("2a20bb73-5717-4635-985a-5d4cf777438f")
            .resourceGroupName("res7687")
            .rules(ObjectReplicationPolicyRuleArgs.builder()
                .destinationContainer("dcont139")
                .filters(ObjectReplicationPolicyFilterArgs.builder()
                    .minCreationTime("2020-02-19T16:05:00Z")
                    .prefixMatch(                    
                        "blobA",
                        "blobB")
                    .build())
                .ruleId("d5d18a48-8801-4554-aeaa-74faf65f5ef9")
                .sourceContainer("scont139")
                .build())
            .sourceAccount("src1122")
            .build());

    }
}
resources:
  objectReplicationPolicy:
    type: azure-native:storage:ObjectReplicationPolicy
    properties:
      accountName: src1122
      destinationAccount: dst112
      metrics:
        enabled: true
      objectReplicationPolicyId: 2a20bb73-5717-4635-985a-5d4cf777438f
      resourceGroupName: res7687
      rules:
        - destinationContainer: dcont139
          filters:
            minCreationTime: 2020-02-19T16:05:00Z
            prefixMatch:
              - blobA
              - blobB
          ruleId: d5d18a48-8801-4554-aeaa-74faf65f5ef9
          sourceContainer: scont139
      sourceAccount: src1122

The objectReplicationPolicyId must match the policy ID from the destination account. Each rule’s ruleId must match the corresponding rule ID from the destination. The minCreationTime filter ensures only blobs created after a specific timestamp are replicated, useful for avoiding large initial sync operations.

Add replication rules to an existing policy

As replication needs grow, you can add new container pairs to an existing policy rather than creating separate policies.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const objectReplicationPolicy = new azure_native.storage.ObjectReplicationPolicy("objectReplicationPolicy", {
    accountName: "dst112",
    destinationAccount: "dst112",
    metrics: {
        enabled: true,
    },
    objectReplicationPolicyId: "2a20bb73-5717-4635-985a-5d4cf777438f",
    resourceGroupName: "res7687",
    rules: [
        {
            destinationContainer: "dcont139",
            filters: {
                prefixMatch: [
                    "blobA",
                    "blobB",
                ],
            },
            ruleId: "d5d18a48-8801-4554-aeaa-74faf65f5ef9",
            sourceContainer: "scont139",
        },
        {
            destinationContainer: "dcont179",
            sourceContainer: "scont179",
        },
    ],
    sourceAccount: "src1122",
});
import pulumi
import pulumi_azure_native as azure_native

object_replication_policy = azure_native.storage.ObjectReplicationPolicy("objectReplicationPolicy",
    account_name="dst112",
    destination_account="dst112",
    metrics={
        "enabled": True,
    },
    object_replication_policy_id="2a20bb73-5717-4635-985a-5d4cf777438f",
    resource_group_name="res7687",
    rules=[
        {
            "destination_container": "dcont139",
            "filters": {
                "prefix_match": [
                    "blobA",
                    "blobB",
                ],
            },
            "rule_id": "d5d18a48-8801-4554-aeaa-74faf65f5ef9",
            "source_container": "scont139",
        },
        {
            "destination_container": "dcont179",
            "source_container": "scont179",
        },
    ],
    source_account="src1122")
package main

import (
	storage "github.com/pulumi/pulumi-azure-native-sdk/storage/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storage.NewObjectReplicationPolicy(ctx, "objectReplicationPolicy", &storage.ObjectReplicationPolicyArgs{
			AccountName:        pulumi.String("dst112"),
			DestinationAccount: pulumi.String("dst112"),
			Metrics: &storage.ObjectReplicationPolicyPropertiesMetricsArgs{
				Enabled: pulumi.Bool(true),
			},
			ObjectReplicationPolicyId: pulumi.String("2a20bb73-5717-4635-985a-5d4cf777438f"),
			ResourceGroupName:         pulumi.String("res7687"),
			Rules: storage.ObjectReplicationPolicyRuleArray{
				&storage.ObjectReplicationPolicyRuleArgs{
					DestinationContainer: pulumi.String("dcont139"),
					Filters: &storage.ObjectReplicationPolicyFilterArgs{
						PrefixMatch: pulumi.StringArray{
							pulumi.String("blobA"),
							pulumi.String("blobB"),
						},
					},
					RuleId:          pulumi.String("d5d18a48-8801-4554-aeaa-74faf65f5ef9"),
					SourceContainer: pulumi.String("scont139"),
				},
				&storage.ObjectReplicationPolicyRuleArgs{
					DestinationContainer: pulumi.String("dcont179"),
					SourceContainer:      pulumi.String("scont179"),
				},
			},
			SourceAccount: pulumi.String("src1122"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var objectReplicationPolicy = new AzureNative.Storage.ObjectReplicationPolicy("objectReplicationPolicy", new()
    {
        AccountName = "dst112",
        DestinationAccount = "dst112",
        Metrics = new AzureNative.Storage.Inputs.ObjectReplicationPolicyPropertiesMetricsArgs
        {
            Enabled = true,
        },
        ObjectReplicationPolicyId = "2a20bb73-5717-4635-985a-5d4cf777438f",
        ResourceGroupName = "res7687",
        Rules = new[]
        {
            new AzureNative.Storage.Inputs.ObjectReplicationPolicyRuleArgs
            {
                DestinationContainer = "dcont139",
                Filters = new AzureNative.Storage.Inputs.ObjectReplicationPolicyFilterArgs
                {
                    PrefixMatch = new[]
                    {
                        "blobA",
                        "blobB",
                    },
                },
                RuleId = "d5d18a48-8801-4554-aeaa-74faf65f5ef9",
                SourceContainer = "scont139",
            },
            new AzureNative.Storage.Inputs.ObjectReplicationPolicyRuleArgs
            {
                DestinationContainer = "dcont179",
                SourceContainer = "scont179",
            },
        },
        SourceAccount = "src1122",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.ObjectReplicationPolicy;
import com.pulumi.azurenative.storage.ObjectReplicationPolicyArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyPropertiesMetricsArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyRuleArgs;
import com.pulumi.azurenative.storage.inputs.ObjectReplicationPolicyFilterArgs;
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 objectReplicationPolicy = new ObjectReplicationPolicy("objectReplicationPolicy", ObjectReplicationPolicyArgs.builder()
            .accountName("dst112")
            .destinationAccount("dst112")
            .metrics(ObjectReplicationPolicyPropertiesMetricsArgs.builder()
                .enabled(true)
                .build())
            .objectReplicationPolicyId("2a20bb73-5717-4635-985a-5d4cf777438f")
            .resourceGroupName("res7687")
            .rules(            
                ObjectReplicationPolicyRuleArgs.builder()
                    .destinationContainer("dcont139")
                    .filters(ObjectReplicationPolicyFilterArgs.builder()
                        .prefixMatch(                        
                            "blobA",
                            "blobB")
                        .build())
                    .ruleId("d5d18a48-8801-4554-aeaa-74faf65f5ef9")
                    .sourceContainer("scont139")
                    .build(),
                ObjectReplicationPolicyRuleArgs.builder()
                    .destinationContainer("dcont179")
                    .sourceContainer("scont179")
                    .build())
            .sourceAccount("src1122")
            .build());

    }
}
resources:
  objectReplicationPolicy:
    type: azure-native:storage:ObjectReplicationPolicy
    properties:
      accountName: dst112
      destinationAccount: dst112
      metrics:
        enabled: true
      objectReplicationPolicyId: 2a20bb73-5717-4635-985a-5d4cf777438f
      resourceGroupName: res7687
      rules:
        - destinationContainer: dcont139
          filters:
            prefixMatch:
              - blobA
              - blobB
          ruleId: d5d18a48-8801-4554-aeaa-74faf65f5ef9
          sourceContainer: scont139
        - destinationContainer: dcont179
          sourceContainer: scont179
      sourceAccount: src1122

The rules array can contain multiple entries, each defining a source-destination container pair. The first rule includes filters and a ruleId from the initial setup; the second rule adds a new container pair. Azure generates a new ruleId for the second rule when you update the policy.

Beyond these examples

These snippets focus on specific policy-level features: destination and source policy configuration, prefix-based filtering and time-based replication, and multi-rule policies for multiple container pairs. They’re intentionally minimal rather than full replication solutions.

The examples reference pre-existing infrastructure such as source and destination storage accounts with blob versioning enabled, and blob containers in both accounts. They focus on configuring the replication policy rather than provisioning the storage infrastructure.

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

  • Cross-tenant replication (allowCrossTenantReplication)
  • Metrics configuration details (metrics.enabled)
  • Policy deletion and lifecycle management
  • Change feed requirements and configuration

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

Let's configure Azure Storage Object Replication Policies

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Policy Setup & Configuration
What's the difference between setting up replication on source vs destination accounts?
Configure the policy on the destination account first using "default" as the objectReplicationPolicyId. Then configure the source account using the actual policy ID (GUID) returned from the destination. The destination policy must be created before the source policy.
What are the naming requirements for storage accounts?
The accountName must be between 3 and 24 characters in length and use numbers and lower-case letters only.
When should I use full resource IDs for source and destination accounts?
Use full resource IDs for sourceAccount and destinationAccount if allowCrossTenantReplication is set to false.
Rules & Filtering
How do I filter which blobs get replicated?
Use the filters property within rules to specify prefixMatch (array of blob name prefixes like ["blobA", "blobB"]) and/or minCreationTime (ISO 8601 timestamp like "2020-02-19T16:05:00Z").
Can I have multiple replication rules in one policy?
Yes, the rules property accepts an array of rules. Each rule can specify its own sourceContainer, destinationContainer, and optional filters.
Do I need to specify a ruleId when creating rules?
When creating a policy on the destination account, ruleId is optional. When creating or updating on the source account, include the ruleId values returned from the destination policy.
Immutability & Updates
What properties can't I change after creating the policy?
The accountName, objectReplicationPolicyId, and resourceGroupName properties are immutable and cannot be modified after resource creation. Changes to these require recreating the resource.
How do I enable metrics for object replication?
Set the metrics property with enabled: true to enable the object replication policy metrics feature.

Using a different cloud?

Explore storage guides for other cloud providers: