The azure-native:resources:Deployment resource, part of the Pulumi Azure Native provider, executes ARM template deployments within a resource group, managing the lifecycle of Azure resources defined in the template. This guide focuses on three capabilities: template deployment from external URIs and Template Specs, automatic rollback on deployment failure, and deployment modes and error handling.
Deployments require an existing resource group and reference ARM templates stored as URLs, Template Specs, or inline JSON. The examples are intentionally small. Combine them with your own templates, parameter files, and resource groups.
Deploy a template from a URI with SAS token
Most Azure deployments reference ARM templates stored in external locations like Azure Storage or GitHub. When templates live in private storage accounts, you need a SAS token to authenticate access.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const deployment = new azure_native.resources.Deployment("deployment", {
deploymentName: "my-deployment",
properties: {
mode: azure_native.resources.DeploymentMode.Incremental,
parameters: {},
templateLink: {
queryString: "sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=xxxxxxxx0xxxxxxxxxxxxx%2bxxxxxxxxxxxxxxxxxxxx%3d",
uri: "https://example.com/exampleTemplate.json",
},
},
resourceGroupName: "my-resource-group",
});
import pulumi
import pulumi_azure_native as azure_native
deployment = azure_native.resources.Deployment("deployment",
deployment_name="my-deployment",
properties={
"mode": azure_native.resources.DeploymentMode.INCREMENTAL,
"parameters": {},
"template_link": {
"query_string": "sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=xxxxxxxx0xxxxxxxxxxxxx%2bxxxxxxxxxxxxxxxxxxxx%3d",
"uri": "https://example.com/exampleTemplate.json",
},
},
resource_group_name="my-resource-group")
package main
import (
resources "github.com/pulumi/pulumi-azure-native-sdk/resources/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := resources.NewDeployment(ctx, "deployment", &resources.DeploymentArgs{
DeploymentName: pulumi.String("my-deployment"),
Properties: &resources.DeploymentPropertiesArgs{
Mode: resources.DeploymentModeIncremental,
Parameters: resources.DeploymentParameterMap{},
TemplateLink: &resources.TemplateLinkArgs{
QueryString: pulumi.String("sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=xxxxxxxx0xxxxxxxxxxxxx%2bxxxxxxxxxxxxxxxxxxxx%3d"),
Uri: pulumi.String("https://example.com/exampleTemplate.json"),
},
},
ResourceGroupName: pulumi.String("my-resource-group"),
})
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 deployment = new AzureNative.Resources.Deployment("deployment", new()
{
DeploymentName = "my-deployment",
Properties = new AzureNative.Resources.Inputs.DeploymentPropertiesArgs
{
Mode = AzureNative.Resources.DeploymentMode.Incremental,
Parameters = null,
TemplateLink = new AzureNative.Resources.Inputs.TemplateLinkArgs
{
QueryString = "sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=xxxxxxxx0xxxxxxxxxxxxx%2bxxxxxxxxxxxxxxxxxxxx%3d",
Uri = "https://example.com/exampleTemplate.json",
},
},
ResourceGroupName = "my-resource-group",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.resources.Deployment;
import com.pulumi.azurenative.resources.DeploymentArgs;
import com.pulumi.azurenative.resources.inputs.DeploymentPropertiesArgs;
import com.pulumi.azurenative.resources.inputs.TemplateLinkArgs;
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 deployment = new Deployment("deployment", DeploymentArgs.builder()
.deploymentName("my-deployment")
.properties(DeploymentPropertiesArgs.builder()
.mode("Incremental")
.parameters(Map.ofEntries(
))
.templateLink(TemplateLinkArgs.builder()
.queryString("sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=xxxxxxxx0xxxxxxxxxxxxx%2bxxxxxxxxxxxxxxxxxxxx%3d")
.uri("https://example.com/exampleTemplate.json")
.build())
.build())
.resourceGroupName("my-resource-group")
.build());
}
}
resources:
deployment:
type: azure-native:resources:Deployment
properties:
deploymentName: my-deployment
properties:
mode: Incremental
parameters: {}
templateLink:
queryString: sv=2019-02-02&st=2019-04-29T22%3A18%3A26Z&se=2019-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=xxxxxxxx0xxxxxxxxxxxxx%2bxxxxxxxxxxxxxxxxxxxx%3d
uri: https://example.com/exampleTemplate.json
resourceGroupName: my-resource-group
The templateLink property points to your template’s location. The uri specifies the template URL, while queryString provides the SAS token for authentication. The mode property controls how Azure applies the template: Incremental adds or updates resources without touching existing ones, while Complete removes resources not defined in the template.
Deploy a versioned template spec by resource ID
Template Specs store and version ARM templates as Azure resources, making them easier to share across teams and enforce governance.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const deployment = new azure_native.resources.Deployment("deployment", {
deploymentName: "my-deployment",
properties: {
mode: azure_native.resources.DeploymentMode.Incremental,
parameters: {},
templateLink: {
id: "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/my-resource-group/providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1",
},
},
resourceGroupName: "my-resource-group",
});
import pulumi
import pulumi_azure_native as azure_native
deployment = azure_native.resources.Deployment("deployment",
deployment_name="my-deployment",
properties={
"mode": azure_native.resources.DeploymentMode.INCREMENTAL,
"parameters": {},
"template_link": {
"id": "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/my-resource-group/providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1",
},
},
resource_group_name="my-resource-group")
package main
import (
resources "github.com/pulumi/pulumi-azure-native-sdk/resources/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := resources.NewDeployment(ctx, "deployment", &resources.DeploymentArgs{
DeploymentName: pulumi.String("my-deployment"),
Properties: &resources.DeploymentPropertiesArgs{
Mode: resources.DeploymentModeIncremental,
Parameters: resources.DeploymentParameterMap{},
TemplateLink: &resources.TemplateLinkArgs{
Id: pulumi.String("/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/my-resource-group/providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1"),
},
},
ResourceGroupName: pulumi.String("my-resource-group"),
})
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 deployment = new AzureNative.Resources.Deployment("deployment", new()
{
DeploymentName = "my-deployment",
Properties = new AzureNative.Resources.Inputs.DeploymentPropertiesArgs
{
Mode = AzureNative.Resources.DeploymentMode.Incremental,
Parameters = null,
TemplateLink = new AzureNative.Resources.Inputs.TemplateLinkArgs
{
Id = "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/my-resource-group/providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1",
},
},
ResourceGroupName = "my-resource-group",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.resources.Deployment;
import com.pulumi.azurenative.resources.DeploymentArgs;
import com.pulumi.azurenative.resources.inputs.DeploymentPropertiesArgs;
import com.pulumi.azurenative.resources.inputs.TemplateLinkArgs;
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 deployment = new Deployment("deployment", DeploymentArgs.builder()
.deploymentName("my-deployment")
.properties(DeploymentPropertiesArgs.builder()
.mode("Incremental")
.parameters(Map.ofEntries(
))
.templateLink(TemplateLinkArgs.builder()
.id("/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/my-resource-group/providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1")
.build())
.build())
.resourceGroupName("my-resource-group")
.build());
}
}
resources:
deployment:
type: azure-native:resources:Deployment
properties:
deploymentName: my-deployment
properties:
mode: Incremental
parameters: {}
templateLink:
id: /subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/my-resource-group/providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1
resourceGroupName: my-resource-group
Instead of a URI, the templateLink.id property references a Template Spec by its full resource ID, including the version path. This approach centralizes template management and ensures teams deploy approved, versioned infrastructure definitions.
Roll back to a specific deployment on failure
Production deployments often need automatic rollback strategies to minimize downtime when new changes fail validation or cause runtime errors.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const deployment = new azure_native.resources.Deployment("deployment", {
deploymentName: "my-deployment",
properties: {
mode: azure_native.resources.DeploymentMode.Complete,
onErrorDeployment: {
deploymentName: "name-of-deployment-to-use",
type: azure_native.resources.OnErrorDeploymentType.SpecificDeployment,
},
parameters: {},
templateLink: {
uri: "https://example.com/exampleTemplate.json",
},
},
resourceGroupName: "my-resource-group",
});
import pulumi
import pulumi_azure_native as azure_native
deployment = azure_native.resources.Deployment("deployment",
deployment_name="my-deployment",
properties={
"mode": azure_native.resources.DeploymentMode.COMPLETE,
"on_error_deployment": {
"deployment_name": "name-of-deployment-to-use",
"type": azure_native.resources.OnErrorDeploymentType.SPECIFIC_DEPLOYMENT,
},
"parameters": {},
"template_link": {
"uri": "https://example.com/exampleTemplate.json",
},
},
resource_group_name="my-resource-group")
package main
import (
resources "github.com/pulumi/pulumi-azure-native-sdk/resources/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := resources.NewDeployment(ctx, "deployment", &resources.DeploymentArgs{
DeploymentName: pulumi.String("my-deployment"),
Properties: &resources.DeploymentPropertiesArgs{
Mode: resources.DeploymentModeComplete,
OnErrorDeployment: &resources.OnErrorDeploymentArgs{
DeploymentName: pulumi.String("name-of-deployment-to-use"),
Type: resources.OnErrorDeploymentTypeSpecificDeployment,
},
Parameters: resources.DeploymentParameterMap{},
TemplateLink: &resources.TemplateLinkArgs{
Uri: pulumi.String("https://example.com/exampleTemplate.json"),
},
},
ResourceGroupName: pulumi.String("my-resource-group"),
})
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 deployment = new AzureNative.Resources.Deployment("deployment", new()
{
DeploymentName = "my-deployment",
Properties = new AzureNative.Resources.Inputs.DeploymentPropertiesArgs
{
Mode = AzureNative.Resources.DeploymentMode.Complete,
OnErrorDeployment = new AzureNative.Resources.Inputs.OnErrorDeploymentArgs
{
DeploymentName = "name-of-deployment-to-use",
Type = AzureNative.Resources.OnErrorDeploymentType.SpecificDeployment,
},
Parameters = null,
TemplateLink = new AzureNative.Resources.Inputs.TemplateLinkArgs
{
Uri = "https://example.com/exampleTemplate.json",
},
},
ResourceGroupName = "my-resource-group",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.resources.Deployment;
import com.pulumi.azurenative.resources.DeploymentArgs;
import com.pulumi.azurenative.resources.inputs.DeploymentPropertiesArgs;
import com.pulumi.azurenative.resources.inputs.OnErrorDeploymentArgs;
import com.pulumi.azurenative.resources.inputs.TemplateLinkArgs;
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 deployment = new Deployment("deployment", DeploymentArgs.builder()
.deploymentName("my-deployment")
.properties(DeploymentPropertiesArgs.builder()
.mode("Complete")
.onErrorDeployment(OnErrorDeploymentArgs.builder()
.deploymentName("name-of-deployment-to-use")
.type("SpecificDeployment")
.build())
.parameters(Map.ofEntries(
))
.templateLink(TemplateLinkArgs.builder()
.uri("https://example.com/exampleTemplate.json")
.build())
.build())
.resourceGroupName("my-resource-group")
.build());
}
}
resources:
deployment:
type: azure-native:resources:Deployment
properties:
deploymentName: my-deployment
properties:
mode: Complete
onErrorDeployment:
deploymentName: name-of-deployment-to-use
type: SpecificDeployment
parameters: {}
templateLink:
uri: https://example.com/exampleTemplate.json
resourceGroupName: my-resource-group
The onErrorDeployment property defines rollback behavior. When type is SpecificDeployment, Azure redeploys the deployment named in deploymentName if the current deployment fails. This provides a safety net for risky changes.
Roll back to the last successful deployment on failure
When you don’t know which specific deployment to roll back to, Azure can automatically identify and redeploy the most recent successful deployment.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const deployment = new azure_native.resources.Deployment("deployment", {
deploymentName: "my-deployment",
properties: {
mode: azure_native.resources.DeploymentMode.Complete,
onErrorDeployment: {
type: azure_native.resources.OnErrorDeploymentType.LastSuccessful,
},
parameters: {},
templateLink: {
uri: "https://example.com/exampleTemplate.json",
},
},
resourceGroupName: "my-resource-group",
});
import pulumi
import pulumi_azure_native as azure_native
deployment = azure_native.resources.Deployment("deployment",
deployment_name="my-deployment",
properties={
"mode": azure_native.resources.DeploymentMode.COMPLETE,
"on_error_deployment": {
"type": azure_native.resources.OnErrorDeploymentType.LAST_SUCCESSFUL,
},
"parameters": {},
"template_link": {
"uri": "https://example.com/exampleTemplate.json",
},
},
resource_group_name="my-resource-group")
package main
import (
resources "github.com/pulumi/pulumi-azure-native-sdk/resources/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := resources.NewDeployment(ctx, "deployment", &resources.DeploymentArgs{
DeploymentName: pulumi.String("my-deployment"),
Properties: &resources.DeploymentPropertiesArgs{
Mode: resources.DeploymentModeComplete,
OnErrorDeployment: &resources.OnErrorDeploymentArgs{
Type: resources.OnErrorDeploymentTypeLastSuccessful,
},
Parameters: resources.DeploymentParameterMap{},
TemplateLink: &resources.TemplateLinkArgs{
Uri: pulumi.String("https://example.com/exampleTemplate.json"),
},
},
ResourceGroupName: pulumi.String("my-resource-group"),
})
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 deployment = new AzureNative.Resources.Deployment("deployment", new()
{
DeploymentName = "my-deployment",
Properties = new AzureNative.Resources.Inputs.DeploymentPropertiesArgs
{
Mode = AzureNative.Resources.DeploymentMode.Complete,
OnErrorDeployment = new AzureNative.Resources.Inputs.OnErrorDeploymentArgs
{
Type = AzureNative.Resources.OnErrorDeploymentType.LastSuccessful,
},
Parameters = null,
TemplateLink = new AzureNative.Resources.Inputs.TemplateLinkArgs
{
Uri = "https://example.com/exampleTemplate.json",
},
},
ResourceGroupName = "my-resource-group",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.resources.Deployment;
import com.pulumi.azurenative.resources.DeploymentArgs;
import com.pulumi.azurenative.resources.inputs.DeploymentPropertiesArgs;
import com.pulumi.azurenative.resources.inputs.OnErrorDeploymentArgs;
import com.pulumi.azurenative.resources.inputs.TemplateLinkArgs;
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 deployment = new Deployment("deployment", DeploymentArgs.builder()
.deploymentName("my-deployment")
.properties(DeploymentPropertiesArgs.builder()
.mode("Complete")
.onErrorDeployment(OnErrorDeploymentArgs.builder()
.type("LastSuccessful")
.build())
.parameters(Map.ofEntries(
))
.templateLink(TemplateLinkArgs.builder()
.uri("https://example.com/exampleTemplate.json")
.build())
.build())
.resourceGroupName("my-resource-group")
.build());
}
}
resources:
deployment:
type: azure-native:resources:Deployment
properties:
deploymentName: my-deployment
properties:
mode: Complete
onErrorDeployment:
type: LastSuccessful
parameters: {}
templateLink:
uri: https://example.com/exampleTemplate.json
resourceGroupName: my-resource-group
Setting onErrorDeployment.type to LastSuccessful tells Azure to find and redeploy the most recent successful deployment automatically. This is simpler than tracking deployment names manually but requires at least one successful deployment in the resource group’s history.
Beyond these examples
These snippets focus on specific deployment-level features: template deployment from URIs and Template Specs, error handling and automatic rollback, and deployment modes. They’re intentionally minimal rather than full infrastructure deployments.
The examples may reference pre-existing infrastructure such as resource groups, ARM templates or Template Specs, and previous successful deployments for rollback scenarios. They focus on configuring the deployment rather than provisioning the templates or resource groups themselves.
To keep things focused, common deployment patterns are omitted, including:
- Template parameters and parameter files
- Inline template definitions (template property)
- Deployment location and tagging
- What-if validation and deployment scopes
These omissions are intentional: the goal is to illustrate how each deployment feature is wired, not provide drop-in infrastructure modules. See the Deployment resource reference for all available configuration options.
Let's deploy Azure Resource Manager Templates
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Deployment Configuration
deploymentName and resourceGroupName are immutable. You’ll need to delete and recreate the deployment to change either property.Template Sources
templateLink with both uri (the template URL) and queryString (containing the SAS token parameters). The queryString keeps the token separate from the URI.templateLink.id to the TemplateSpec resource ID (e.g., /subscriptions/.../providers/Microsoft.Resources/TemplateSpecs/TemplateSpec-Name/versions/v1).queryString parameter holds SAS token parameters when deploying templates from Azure Storage, keeping authentication separate from the template URI.Error Handling & Rollback
Use onErrorDeployment with type set to either:
LastSuccessfulto rollback to the last successful deploymentSpecificDeployment(withdeploymentName) to rollback to a specific deployment
API Versions
pulumi package add azure-native resources [ApiVersion]. Available versions include 2020-10-01, 2021-01-01, 2021-04-01, 2022-09-01, 2023-07-01, 2024-07-01, 2024-11-01, 2025-03-01, and 2025-04-01.