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 storage accounts. This guide focuses on three capabilities: destination-side policy creation, source-side policy linking, and multi-rule policy updates.

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

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 to configure the source account.

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 needs its ruleId from the destination policy. The minCreationTime property limits replication to blobs created after a specific timestamp, useful for avoiding large initial sync operations. This completes the bidirectional link: the source account now knows where to send replicated blobs.

Add replication rules to an existing policy

Policies can be updated to replicate additional container pairs without disrupting existing replication.

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

You can add new rules to the rules array while keeping existing ones. Each rule operates independently, so adding a second rule (scont179 to dcont179) doesn’t affect the first rule’s replication. The second rule omits filters, meaning it replicates all blobs in the source container.

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. They’re intentionally minimal rather than full replication deployments.

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

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

  • Change feed enablement (required Azure prerequisite)
  • Cross-tenant replication (allowCrossTenantReplication)
  • Metrics configuration details (metrics.enabled shown but not explained)
  • Policy deletion and lifecycle management

These omissions are intentional: the goal is to illustrate how each policy feature is wired, not provide drop-in replication 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

Setup & Configuration
How do I set up object replication between two storage accounts?

Object replication requires a two-step setup process:

  1. Destination account: Create the policy with objectReplicationPolicyId set to "default"
  2. Source account: Create the policy using the policyId returned from the destination (a UUID)

Configure accountName to match whichever account you’re setting up in each step.

What's the difference between accountName, sourceAccount, and destinationAccount?
accountName specifies where you’re configuring the policy (immutable). sourceAccount and destinationAccount (both required) identify the two storage accounts involved in replication. When configuring the destination, accountName matches destinationAccount. When configuring the source, accountName matches sourceAccount.
Rules & Filtering
How do I filter which blobs get replicated?

Use the filters property within each rule. You can specify:

  • prefixMatch: Array of blob name prefixes (e.g., ["blobA", "blobB"])
  • minCreationTime: ISO 8601 timestamp to replicate only blobs created after this time
Can I add rules to an existing replication policy?
Yes, update the policy by including both existing and new rules. On the destination account, omit ruleId for new rules. On the source account, specify ruleId for all rules (existing and new).
Policy IDs & Immutability
When should I use 'default' vs a UUID for objectReplicationPolicyId?
Use "default" when creating the policy on the destination account. Use the UUID returned from the destination’s policyId output when creating the policy on the source account.
What properties can't be changed after creation?
accountName, objectReplicationPolicyId, and resourceGroupName are immutable. Changing any of these requires recreating the resource.
Cross-Tenant Replication
What format is required for cross-tenant replication?
When allowCrossTenantReplication is set to false, both sourceAccount and destinationAccount must be specified as full resource IDs rather than just account names.
How do I enable metrics for my replication policy?
Set the metrics property with enabled: true to enable object replication policy metrics.

Using a different cloud?

Explore storage guides for other cloud providers: