The azurerm storage account resource represents the Terraform managed interface to an Azure Storage Account and the azurerm backend provides the mechanism to store Terraform state as a blob object inside that storage account. The two concerns intersect in production environments because the storage account that backs Terraform state is itself frequently provisioned with Terraform using the azurermstorageaccount resource. The resource definition controls the creation and lifecycle of the storage account, while the backend configuration controls how Terraform authenticates to the storage account data plane to read and write the state file blob. Both surfaces carry mandatory naming constraints, location binding, replication and tier selection, network isolation options, and timeout defaults that affect real world deployment cost, availability, and security posture. Operators must understand the argument surface, the conditional feature blocks, the import workflow, and the backend credential handling to avoid state loss, accidental recreation, or exposure of secrets.
Resource Argument Reference
The azurermstorageaccount resource requires a set of core arguments that define the identity and placement of the storage account within Azure.
The name argument specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group.
The resourcegroupname argument is the name of the resource group in which to create the storage account. Changing this forces a new resource to be created.
The location argument specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created.
The accounttype argument defines the type of storage account to be created. Valid options are StandardLRS, StandardZRS, StandardGRS, StandardRAGRS, PremiumLRS. Changing this is sometimes valid, see the Azure documentation for more information on which types of accounts can be converted into other types.
The enableblobencryption argument is a boolean flag which controls if Encryption Services are enabled for Blob storage.
A structured view of the core arguments is shown below.
| Argument | Requirement | Description |
| name | Required | Specifies the name of the storage account. Changing this forces a new resource to be created. This must be unique across the entire Azure service, not just within the resource group. |
| resourcegroupname | Required | The name of the resource group in which to create the storage account. Changing this forces a new resource to be created. |
| location | Required | Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. |
| accounttype | Required | Defines the type of storage account to be created. Valid options are StandardLRS, StandardZRS, StandardGRS, StandardRAGRS, PremiumLRS. Changing this is sometimes valid. |
| enableblobencryption | Optional | Boolean flag which controls if Encryption Services are enabled for Blob storage. |
The impact of the uniqueness requirement for name is that a naming collision across tenants prevents creation and forces the operator to select a new globally unique name. The impact of force new on name, resourcegroupname, and location is that any change to those values triggers destruction of the existing storage account and creation of a replacement, which leads to data loss unless data is migrated. The contextual relationship is that resourcegroupname and location are linked to the resource group used in the same configuration, so drift in the resource group propagates to the storage account.
Example Configurations
Example usage from the provider documentation shows the classic pattern of creating a resource group and then a storage account referencing it.
resource "azurerm_resource_group" "testrg" {
name = "resourceGroupName"
location = "westus"
}
resource "azurerm_storage_account" "testsa" {
name = "storageaccountname"
resource_group_name = "${azurerm_resource_group.testrg.name}"
location = "westus"
account_type = "Standard_GRS"
tags {
environment = "staging"
}
}
The example demonstrates name binding via interpolation, location mirroring, account_type selection, and tag assignment. The tag block with environment equal to staging provides cost allocation and governance filtering.
A second example uses the accounttier and accountreplication_type split that appears in later documentation.
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_storage_account" "example" {
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
tags = {
environment = "staging"
}
}
The impact of using accounttier and accountreplication_type is separation of performance tier from replication strategy, which gives finer control over cost and durability. The contextual connection is that the same resource group and location are reused, maintaining placement consistency.
A network restricted variant is also documented.
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_virtual_network" "example" {
name = "virtnetname"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_subnet" "example" {
name = "subnetname"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.0.2.0/24"]
service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"]
}
resource "azurerm_storage_account" "example" {
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
network_rules {
default_action = "Deny"
ip_rules = ["100.0.0.1"]
virtual_network_subnet_ids = [azurerm_subnet.example.id]
}
tags = {
environment = "staging"
}
}
The networkrules block with defaultaction Deny, iprules, and virtualnetworksubnetids restricts ingress to a specific IP and a specific subnet. The impact is reduced exposure surface for the storage account. The contextual link is the service_endpoints configuration on the subnet for Microsoft.Storage, which allows Azure services to reach the storage account without traversing the public internet.
Replication, Tier and Account Type Mapping
The accounttype field consolidates tier and replication into a single string. The split model uses accounttier and accountreplicationtype.
Valid accounttype values include StandardLRS, StandardZRS, StandardGRS, StandardRAGRS, PremiumLRS.
The accounttier value Standard is used together with accountreplication_type values such as GRS or LRS.
The mapping between the two models matters during migration and documentation interpretation. Operators must not mix accounttype with accounttier in the same resource because the provider treats them as distinct schemas.
| Model | Fields | Example |
| Consolidated | accounttype | StandardGRS |
| Split | accounttier + accountreplicationtype | accounttier = "Standard", accountreplicationtype = "GRS" |
The impact of choosing GRS versus LRS is durability and recovery time objective. GRS provides asynchronous geo replication to a paired region, which increases resilience against regional outages at higher cost. LRS keeps data within a single region with local redundancy, reducing cost. The contextual relationship is that network_rules and service endpoints further shape the effective availability of the replicated data.
Optional Feature Blocks and Conditional Constraints
The resource supports a number of optional blocks with conditional applicability.
The identity block is optional. An identity block as defined below can be configured.
The blob_properties block is optional.
The queueproperties block is optional. Note that queueproperties can only be configured when accounttier is set to Standard and accountkind is set to either Storage or StorageV2.
The staticwebsite block is optional. Note that staticwebsite can only be set when the accountkind is set to StorageV2 or BlockBlobStorage. Note that if staticwebsite is specified, the service will automatically create a azurermstoragecontainer named $web.
The shareproperties block is optional. Note that shareproperties can only be configured when either accounttier is Standard and accountkind is either Storage or StorageV2 or when accounttier is Premium and accountkind is FileStorage.
The network_rules block is optional and is documented below.
The largefileshareenabled argument is optional. Are Large File Shares Enabled defaults to false. Note that Large File Shares are enabled by default when using an accountkind of FileStorage.
The localuserenabled argument is optional. Is Local User Enabled defaults to true.
The azurefilesauthentication block is optional.
The tenantid attribute is exposed for the Service Principal associated with the Identity of this Storage Account. Note that you can access the Principal ID via ${azurermstorageaccount.example.identity[0].principalid} and the Tenant ID via ${azurermstorageaccount.example.identity[0].tenant_id}.
These conditional constraints prevent configuration errors that would otherwise be accepted syntactically but rejected by the Azure Resource Manager API. The impact is that attempts to configure queueproperties on a Premium FileStorage account will fail validation. The contextual link is that staticwebsite creation of the $web container couples the storage account configuration to container management.
Timeouts, Import and Provider API
The timeouts block allows you to specify timeouts for certain actions.
| Action | Default |
| create | 1 hour |
| read | 5 minutes |
| update | 1 hour |
| delete | 1 hour |
Storage Accounts can be imported using the resource id, e.g.
terraform import azurerm_storage_account.storageAcc1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount
The resource uses the following Azure API Providers.
| Provider | API Version |
| Microsoft.Storage | 2025-08-01 |
The impact of timeout defaults is that long running create or delete operations will not be prematurely terminated by Terraform. The impact of import is that existing storage accounts can be brought under Terraform management without recreation. The contextual link is that changing name, resourcegroupname or location forces new resource, so import is the only safe path for existing accounts.
Backend azurerm for Remote State
The azurerm backend stores the state as a Blob with the given Key within the Blob Container within the Blob Storage Account.
This backend supports state locking and consistency checking with Azure Blob Storage native capabilities.
Warning: We recommend using environment variables to supply credentials and other sensitive data. If you use -backend-config or hardcode these values directly in your configuration, Terraform will include these values in both the .terraform subdirectory and in plan files. Refer to Credentials and Sensitive Data for details.
The azurerm backend needs to authenticate to the storage account data plane in order to manipulate the state file blob in the storage account container.
To configure the backend state, you need the following Azure storage information.
- storageaccountname: The name of the Azure Storage account.
- container_name: The name of the blob container.
- key: The name of the state store file to be created.
- access_key: The storage access key.
Each of these values can be specified in the Terraform configuration file or on the command line. We recommend that you use an environment variable for the access_key value.
The impact of storing state in Azure Blob Storage is centralized state with locking, which prevents concurrent applies from corrupting state. The impact of using an Access Key is that the key grants broad data plane access and must be protected. The contextual relationship is that the storage account used for state is itself often provisioned with azurermstorageaccount, creating a dependency loop that must be bootstrapped.
Security and Operational Guidance
Terraform state is stored in plain text and may contain secrets. If the state is incorrectly secured, unauthorized access to systems and data loss can result.
In this example, Terraform authenticates to the Azure storage account using an Access Key. In a production deployment, it's recommended to evaluate the available authentication options supported by the azurerm backend and to use the most secure option for your use case.
In this example, public network access is allowed to this Azure storage account. In a production deployment, it's recommended to restrict access to this storage account using a storage firewall, service endpoint, or private endpoint.
To learn more about troubleshooting storage account names, see Resolve errors for storage account names.
When using the azurermstorageaccountcustomermanagedkey resource, you will need to use ignorechanges on the customermanagedkey block.
The impact of plain text state is that any reader of the state file can discover resource names, secrets, and configuration. The impact of public network access is increased attack surface for brute force and internet originated threats. The contextual link is that networkrules with defaultaction Deny and virtualnetworksubnet_ids reduces that exposure, aligning with the recommendation to restrict access.
Conclusion
The azurermstorageaccount resource and the azurerm backend together form the foundation for stateful Terraform workflows on Azure. The resource defines a strongly constrained set of mandatory arguments for name, resourcegroupname, and location with force new semantics that protect against accidental in place mutation. The accounttype versus accounttier and accountreplicationtype duality reflects provider evolution and requires careful schema selection. Optional blocks for identity, blobproperties, queueproperties, staticwebsite, shareproperties, networkrules, largefileshareenabled, localuserenabled, and azurefilesauthentication expand the capability surface but are gated by conditional constraints tied to accounttier and accountkind. Timeouts defaults and import support provide operational stability for long running operations and adoption of existing infrastructure. The azurerm backend leverages the same storage account to persist state as a blob with native locking and consistency checks, but introduces credential management concerns because state contains secrets and the backend must authenticate to the data plane. Security guidance emphasizes environment variable credential handling, avoidance of hardcoded access keys, restriction of public network access via firewalls, service endpoints, or private endpoints, and awareness of storage account name uniqueness rules. Understanding the interaction between resource creation, network isolation, and backend state storage is essential to avoid recreation, data loss, and exposure of sensitive information in production environments.