Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Important
Items marked (preview) in this article are currently in public preview. This preview is provided without a service-level agreement, and we don't recommend it for production workloads. Certain features might not be supported or might have constrained capabilities. For more information, see Supplemental Terms of Use for Microsoft Azure Previews.
Configure bring-your-own-storage (BYOS) for Speech and Language capabilities in a Foundry resource by setting the userOwnedStorage binding at creation time. This binding routes Speech and Language data to your Azure Storage account while maintaining backward compatibility with earlier standalone resource patterns.
Tip
Use this article when you specifically need Speech and Language data to land in storage you own. For the broader approaches (connections, capability hosts), see Connect to your own storage.
Prerequisites
An Azure account with an active subscription. If you don't have one, create a free Azure account, which includes a free trial subscription.
- An Azure Storage account (Blob) in a region supported by your Foundry resource.
- Resource group permissions:
OwnerorContributorrole on the resource group containing the Foundry resource. - Storage account permissions:
Storage Blob Data Contributorrole on the storage account (assigned to the Foundry resource's managed identity). - (Optional) Customer-managed keys (CMK) configured on the storage account if you require CMK encryption.
Important
Set the userOwnedStorage binding when you create the resource. You can't change this binding later. Review the restrictions before proceeding.
Understand restrictions
Review these constraints before configuring userOwnedStorage:
| Restriction | Details |
|---|---|
| Single account | You can set only one storage account for Speech & Language. |
| Creation time only | Must be set during resource creation; can't add or change afterward. |
| Non-removable | You can't remove or swap the storage account post-creation. |
| Deletion impact | If you delete or move the storage account (resource ID changes), Speech & Language stop functioning. Attempt storage account recovery first; otherwise you must recreate the Foundry resource. |
| Shared across both capabilities | Speech and Language share the same account (distinct containers). For strict isolation, create separate Foundry resources and storage accounts. |
| Data access scope | Any user with access to the Foundry resource can access Speech & Language outputs; project-level isolation doesn’t apply for this binding. |
Configure authentication
Speech and Language support only Azure role-based access control (RBAC) through the resource’s managed identity.
- Ensure the Foundry resource has a system-assigned managed identity.
- On the storage account, assign the
Storage Blob Data Contributorrole to the Foundry resource’s managed identity. - Don't assign the role to individual project identities for this scenario.
API key–based authentication isn't supported.
Example (Azure CLI) – role assignment
STORAGE_ID=/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storageName>
FOUNDRY_ID=/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<foundryName>
# Assign Storage Blob Data Contributor
az role assignment create \
--assignee-object-id $(az resource show --ids $FOUNDRY_ID --query identity.principalId -o tsv) \
--assignee-principal-type ServicePrincipal \
--role "Storage Blob Data Contributor" \
--scope $STORAGE_ID
If successful, the command returns a JSON object with the role assignment details including principalId and roleDefinitionId.
Reference: az role assignment create | az resource show
Example (PowerShell) – role assignment
$storage = "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storageName>"
$foundry = "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<foundryName>"
$principalId = (Get-AzResource -ResourceId $foundry).Identity.PrincipalId
New-AzRoleAssignment -ObjectId $principalId -RoleDefinitionName "Storage Blob Data Contributor" -Scope $storage
If successful, the command returns a RoleAssignment object with the DisplayName, ObjectId, and Scope properties.
Reference: New-AzRoleAssignment | Get-AzResource
Create resource with storage account
Set the userOwnedStorage field during resource creation.
Bicep template snippet
resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
name: storageName
}
resource foundry 'Microsoft.CognitiveServices/accounts@2025-06-01' = {
name: foundryName
location: location
kind: 'AIServices'
sku: { name: 'S0' }
identity: {
type: 'SystemAssigned'
}
properties: {
userOwnedStorage: {
storageResourceId: storage.id
}
}
}
Reference: Microsoft.CognitiveServices/accounts | Microsoft.Storage/storageAccounts
ARM template snippet
{
"type": "Microsoft.CognitiveServices/accounts",
"apiVersion": "2025-06-01",
"name": "[parameters('foundryName')]",
"location": "[parameters('location')]",
"kind": "AIServices",
"identity": { "type": "SystemAssigned" },
"sku": { "name": "S0" },
"properties": {
"userOwnedStorage": {
"storageResourceId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageName'))]"
}
}
}
Reference: Microsoft.CognitiveServices/accounts | ARM template functions
Terraform snippet
Refer to the Terraform cognitive_account documentation.
resource "azurerm_cognitive_account" "foundry" {
name = var.foundry_name
location = var.location
resource_group_name = azurerm_resource_group.rg.name
kind = "AIServices"
sku_name = "S0"
# userOwnedStorage equivalent
storage {
storage_account_id = azurerm_storage_account.speechlang.id
}
identity {
type = "SystemAssigned"
}
}
Reference: azurerm_cognitive_account | azurerm_storage_account
Sample repository
See the infrastructure examples (including Speech/Language storage) in the Foundry samples repository.
Speech integration details
Speech scenarios (Speech-to-Text batch or real-time, Custom Speech, Text-to-Speech, Custom Voice) conform to the guidance in Bring your own storage (BYOS) Speech resource. When you set userOwnedStorage, those outputs route to the bound storage account containers.
Customer-managed keys (CMK)
If you configure customer-managed keys encryption on the storage account, Speech data written there uses those keys. If you don't set userOwnedStorage, Speech falls back to Microsoft-managed storage and doesn't inherit CMK settings from the Foundry resource.
Language integration details
The userOwnedStorage binding mirrors historical Language resource behavior with one key difference: you can't update or replace the storage account after deletion or move. In standalone Language resources, an update is possible. In the unified Foundry resource, it isn't. Plan lifecycle mitigation accordingly.
Shared storage configuration
Speech and Language share the same storage account. Different container naming conventions keep data logically separated. Because access is at the resource scope, any resource-level user can reach both sets of outputs. For stricter separation, deploy distinct resources.
Verify the configuration
After creating the resource with userOwnedStorage, confirm the binding is active:
- In the Azure portal, go to your Foundry resource.
- Select Resource Management > Properties and verify the User Owned Storage field displays your storage account resource ID.
- Run a test Speech or Language operation (for example, a batch transcription job) and confirm the output appears in a container within your storage account.
If the storage binding isn't visible or operations fail, see the troubleshooting section.
Troubleshooting
| Issue | Mitigation |
|---|---|
| Accidental deletion of storage account | Attempt recovering the account. If unsuccessful, recreate the Foundry resource. |
| Role assignment missing | Re-run RBAC role assignment for the resource managed identity on the storage account. |
| Moved storage to new subscription | Recreate resource; moving changes the resource ID and breaks binding. |