Move Azure resources to a new resource group or subscription

This article shows you how to move Azure resources to either another Azure subscription or another resource group under the same subscription. You can use the Azure portal, Azure PowerShell, Azure CLI, or the REST API to move resources.

Both the source group and the target group are locked during the move operation. Write and delete operations are blocked on the resource groups until the move completes. This lock means you can't add, update, or delete resources in the resource groups. It doesn't mean the resources are frozen. For example, if you move an Azure SQL logical server, its databases and other dependent resources to a new resource group or subscription, applications that use the databases experience no downtime. They can still read and write to the databases. The lock can last for a maximum of four hours, but most moves complete in much less time.

If your move requires setting up new dependent resources, you'll experience an interruption in those services until they've been reconfigured.

Moving a resource only moves it to a new resource group or subscription. It doesn't change the location of the resource.

Changed resource ID

When you move a resource, you change its resource ID. The standard format for a resource ID is /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. When you move a resource to a new resource group or subscription, you change one or more values in that path.

If you use the resource ID anywhere, you'll need to change that value. For example, if you have a custom dashboard in the portal that references a resource ID, you'll need to update that value. Look for any scripts or templates that need to be updated for the new resource ID.

Checklist before moving resources

There are some important steps to do before moving a resource. By verifying these conditions, you can avoid errors.

  1. The source and destination subscriptions must be active. If you have trouble enabling an account that has been disabled, create an Azure support request. Select Subscription Management for the issue type.

  2. The source and destination subscriptions must exist within the same Microsoft Entra tenant. To check that both subscriptions have the same tenant ID, use Azure PowerShell or Azure CLI.

    For Azure PowerShell, use:

    (Get-AzSubscription -SubscriptionName <your-source-subscription>).TenantId
    (Get-AzSubscription -SubscriptionName <your-destination-subscription>).TenantId
    

    For Azure CLI, use:

    az account show --subscription <your-source-subscription> --query tenantId
    az account show --subscription <your-destination-subscription> --query tenantId
    

    If the tenant IDs for the source and destination subscriptions aren't the same, use the following methods to reconcile the tenant IDs:

  3. If you're attempting to move resources to or from a Cloud Solution Provider (CSP) partner, see Transfer Azure subscriptions between subscribers and CSPs.

  4. The resources you want to move must support the move operation. For a list of which resources support move, see Move operation support for resources.

  5. Some services have specific limitations or requirements when moving resources. If you're moving any of the following services, check that guidance before moving.

  6. The destination subscription must be registered for the resource provider of the resource being moved. If not, you receive an error stating that the subscription is not registered for a resource type. You might see this error when moving a resource to a new subscription, but that subscription has never been used with that resource type.

    For PowerShell, use the following commands to get the registration status:

    Set-AzContext -Subscription <destination-subscription-name-or-id>
    Get-AzResourceProvider -ListAvailable | Select-Object ProviderNamespace, RegistrationState
    

    To register a resource provider, use:

    Register-AzResourceProvider -ProviderNamespace Microsoft.Batch
    

    For Azure CLI, use the following commands to get the registration status:

    az account set -s <destination-subscription-name-or-id>
    az provider list --query "[].{Provider:namespace, Status:registrationState}" --out table
    

    To register a resource provider, use:

    az provider register --namespace Microsoft.Batch
    
  7. Before moving the resources, check the subscription quotas for the subscription you're moving the resources to. If moving the resources means the subscription will exceed its limits, you need to review whether you can request an increase in the quota. For a list of limits and how to request an increase, see Azure subscription and service limits, quotas, and constraints.

  8. The account moving the resources must have at least the following permissions:

    • Microsoft.Resources/subscriptions/resourceGroups/moveResources/action on the source resource group.
    • Microsoft.Resources/subscriptions/resourceGroups/write on the destination resource group.
  9. If you move a resource that has an Azure role assigned directly to the resource (or a child resource), the role assignment isn't moved and becomes orphaned. After the move, you must re-create the role assignment. Eventually, the orphaned role assignment is automatically removed, but we recommend removing the role assignment before the move.

    For information about how to manage role assignments, see List Azure role assignments and Assign Azure roles.

  10. For a move across subscriptions, the resource and its dependent resources must be located in the same resource group and they must be moved together. For example, a VM with managed disks would require the VM and the managed disks to be moved together, along with other dependent resources.

    If you're moving a resource to a new subscription, check to see whether the resource has any dependent resources, and whether they're located in the same resource group. If the resources aren't in the same resource group, check to see whether the resources can be combined into the same resource group. If so, bring all these resources into the same resource group by using a move operation across resource groups.

    For more information, see Scenario for move across subscriptions.

Scenario for move across subscriptions

Moving resources from one subscription to another is a three-step process:

Diagram that shows the three-step process of moving resources across subscriptions.

For illustration purposes, we have only one dependent resource.

  • Step 1: If dependent resources are distributed across different resource groups, first move them into one resource group.
  • Step 2: Move the resource and dependent resources together from the source subscription to the target subscription.
  • Step 3: Optionally, redistribute the dependent resources to different resource groups within the target subscription.

Use the portal

To move resources, select the resource group that contains those resources.

Select the resources you want to move. To move all of the resources, select the checkbox at the top of list. Or, select resources individually.

Screenshot of the Azure portal showing the selection of resources to move.

Select the Move button.

Screenshot of the Azure portal displaying the Move button with three options.

This button gives you three options:

Select whether you're moving the resources to a new resource group or a new subscription.

The source resource group is automatically set. Specify the destination resource group. If you're moving to a new subscription, also specify the subscription. Select Next.

Screenshot of the Azure portal where the user specifies the destination resource group for the move operation.

The portal validates that the resources can be moved. Wait for validation to complete.

Screenshot of the Azure portal showing the validation process for the move operation.

When validation completes successfully, select Next.

Acknowledge that you need to update tools and scripts for these resources. To start moving the resources, select Move.

Screenshot of the Azure portal where the user acknowledges the need to update tools and scripts before starting the move operation.

When the move has completed, you're notified of the result.

Screenshot of the Azure portal displaying a notification with the results of the move operation.

Use Azure PowerShell

Validate

To test your move scenario without actually moving the resources, use the Invoke-AzResourceAction command. Use this command only when you need to predetermine the results.

$sourceName = "sourceRG"
$destinationName = "destinationRG"
$resourcesToMove = @("app1", "app2")

$sourceResourceGroup = Get-AzResourceGroup -Name $sourceName
$destinationResourceGroup = Get-AzResourceGroup -Name $destinationName

$resources = Get-AzResource -ResourceGroupName $sourceName | Where-Object { $_.Name -in $resourcesToMove }

Invoke-AzResourceAction -Action validateMoveResources `
   -ResourceId $sourceResourceGroup.ResourceId `
   -Parameters @{
      resources = $resources.ResourceId;  # Wrap in an @() array if providing a single resource ID string.
      targetResourceGroup = $destinationResourceGroup.ResourceId
   }

If validation passes, you see no output.

If validation fails, you see an error message describing why the resources can't be moved.

Move

To move existing resources to another resource group or subscription, use the Move-AzResource command. The following example shows how to move several resources to a new resource group.

$sourceName = "sourceRG"
$destinationName = "destinationRG"
$resourcesToMove = @("app1", "app2")

$resources = Get-AzResource -ResourceGroupName $sourceName | Where-Object { $_.Name -in $resourcesToMove }

Move-AzResource -DestinationResourceGroupName $destinationName -ResourceId $resources.ResourceId

To move to a new subscription, include a value for the DestinationSubscriptionId parameter.

Use Azure CLI

Validate

To test your move scenario without actually moving the resources, use the az resource invoke-action command. Use this command only when you need to predetermine the results. To run this operation, you need the:

  • Resource ID of the source resource group
  • Resource ID of the target resource group
  • Resource ID of each resource to move

In the request body, use \" to escape double quotes.

az resource invoke-action --action validateMoveResources \
  --ids "/subscriptions/{subscription-id}/resourceGroups/{source-rg}" \
  --request-body "{  \"resources\": [\"/subscriptions/{subscription-id}/resourceGroups/{source-rg}/providers/{resource-provider}/{resource-type}/{resource-name}\", \"/subscriptions/{subscription-id}/resourceGroups/{source-rg}/providers/{resource-provider}/{resource-type}/{resource-name}\", \"/subscriptions/{subscription-id}/resourceGroups/{source-rg}/providers/{resource-provider}/{resource-type}/{resource-name}\"],\"targetResourceGroup\":\"/subscriptions/{subscription-id}/resourceGroups/{destination-rg}\" }" 

If validation passes, you see:

{} Finished .. 

If validation fails, you see an error message describing why the resources can't be moved.

Move

To move existing resources to another resource group or subscription, use the az resource move command. In the --ids parameter, provide a space-separated list of the resource IDs to move.

The following example shows how to move several resources to a new resource group. It works when using Azure CLI in a Bash terminal.

webapp=$(az resource show -g OldRG -n ExampleSite --resource-type "Microsoft.Web/sites" --query id --output tsv)
plan=$(az resource show -g OldRG -n ExamplePlan --resource-type "Microsoft.Web/serverfarms" --query id --output tsv)
az resource move --destination-group newgroup --ids $webapp $plan

The next example shows how to run the same commands in a PowerShell console.

$webapp=$(az resource show -g OldRG -n ExampleSite --resource-type "Microsoft.Web/sites" --query id --output tsv)
$plan=$(az resource show -g OldRG -n ExamplePlan --resource-type "Microsoft.Web/serverfarms" --query id --output tsv)
az resource move --destination-group newgroup --ids $webapp $plan

To move to a new subscription, provide the --destination-subscription-id parameter.

Use Python

Validate

To test your move scenario without actually moving the resources, use the ResourceManagementClient.resources.begin_validate_move_resources method. Use this method only when you need to predetermine the results.

import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ResourceManagementClient

credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]

resource_client = ResourceManagementClient(credential, subscription_id)

source_name = "sourceRG"
destination_name = "destinationRG"
resources_to_move = ["app1", "app2"]

destination_resource_group = resource_client.resource_groups.get(destination_name)

resources = [
    resource for resource in resource_client.resources.list_by_resource_group(source_name)
    if resource.name in resources_to_move
]

resource_ids = [resource.id for resource in resources]

validate_move_resources_result = resource_client.resources.begin_validate_move_resources(
    source_name,
    {
        "resources": resource_ids,
        "target_resource_group": destination_resource_group.id
    }
).result()

print("Validate move resources result: {}".format(validate_move_resources_result))

If validation passes, you see no output.

If validation fails, you see an error message describing why the resources can't be moved.

Move

To move existing resources to another resource group or subscription, use the ResourceManagementClient.resources.begin_move_resources method. The following example shows how to move several resources to a new resource group.

import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ResourceManagementClient

credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]

resource_client = ResourceManagementClient(credential, subscription_id)

source_name = "sourceRG"
destination_name = "destinationRG"
resources_to_move = ["app1", "app2"]

destination_resource_group = resource_client.resource_groups.get(destination_name)

resources = [
    resource for resource in resource_client.resources.list_by_resource_group(source_name)
    if resource.name in resources_to_move
]

resource_ids = [resource.id for resource in resources]

resource_client.resources.begin_move_resources(
    source_name,
    {
        "resources": resource_ids,
        "target_resource_group": destination_resource_group.id
    }
)

Use REST API

Validate

The validate move operation lets you test your move scenario without actually moving the resources. Use this operation to check if the move will succeed. Validation is automatically called when you send a move request. Use this operation only when you need to predetermine the results. To run this operation, you need the:

  • Name of the source resource group
  • Resource ID of the target resource group
  • Resource ID of each resource to move
  • The access token for your account

Send the following request:

POST https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<source-group>/validateMoveResources?api-version=2019-05-10
Authorization: Bearer <access-token>
Content-type: application/json

With a request body:

{
 "resources": ["<resource-id-1>", "<resource-id-2>"],
 "targetResourceGroup": "/subscriptions/<subscription-id>/resourceGroups/<target-group>"
}

If the request is formatted correctly, the operation returns:

Response Code: 202
cache-control: no-cache
pragma: no-cache
expires: -1
location: https://management.azure.com/subscriptions/<subscription-id>/operationresults/<operation-id>?api-version=2018-02-01
retry-after: 15
...

The 202 status code indicates the validation request was accepted, but it hasn't yet determined if the move operation will succeed. The location value contains a URL that you use to check the status of the long-running operation.

To check the status, send the following request:

GET <location-url>
Authorization: Bearer <access-token>

While the operation is still running, you continue to receive the 202 status code. Wait the number of seconds indicated in the retry-after value before trying again. If the move operation validates successfully, you receive the 204 status code. If the move validation fails, you receive an error message, such as:

{"error":{"code":"ResourceMoveProviderValidationFailed","message":"<message>"...}}

Move

To move existing resources to another resource group or subscription, use the Move resources operation.

POST https://management.azure.com/subscriptions/{source-subscription-id}/resourcegroups/{source-resource-group-name}/moveResources?api-version={api-version}

In the request body, you specify the target resource group and the resources to move.

{
 "resources": ["<resource-id-1>", "<resource-id-2>"],
 "targetResourceGroup": "/subscriptions/<subscription-id>/resourceGroups/<target-group>"
}

Frequently asked questions

Question: My resource move operation, which usually takes a few minutes, has been running for almost an hour. Is there something wrong?

Moving a resource is a complex operation that has different phases. It can involve more than just the resource provider of the resource you're trying to move. Because of the dependencies between resource providers, Azure Resource Manager allows 4 hours for the operation to complete. This time period gives resource providers a chance to recover from transient issues. If your move request is within the four-hour period, the operation keeps trying to complete and may still succeed. The source and destination resource groups are locked during this time to avoid consistency issues.

Question: Why is my resource group locked for four hours during resource move?

A move request is allowed a maximum of four hours to complete. To prevent modifications on the resources being moved, both the source and destination resource groups are locked during the resource move.

There are two phases in a move request. In the first phase, the resource is moved. In the second phase, notifications are sent to other resource providers that are dependent on the resource being moved. A resource group can be locked for the entire four hours when a resource provider fails either phase. During the allowed time, Resource Manager retries the failed step.

If a resource can't be moved within four hours, Resource Manager unlocks both resource groups. Resources that were successfully moved are in the destination resource group. Resources that failed to move are left the source resource group.

Question: What are the implications of the source and destination resource groups being locked during the resource move?

The lock prevents you from deleting either resource group, creating a new resource in either resource group, or deleting any of the resources involved in the move.

The following image shows an error message from the Azure portal when a user tries to delete a resource group that is part of an ongoing move.

Screenshot of the Azure portal showing an error message when trying to delete a resource group involved in an ongoing move operation.

Question: What does the error code "MissingMoveDependentResources" mean?

When you move a resource, its dependent resources must either exist in the destination resource group or subscription, or be included in the move request. You get the MissingMoveDependentResources error code when a dependent resource doesn't meet this requirement. The error message has details about the dependent resource that needs to be included in the move request.

For example, moving a virtual machine could require moving seven resource types with three different resource providers. Those resource providers and types are:

  • Microsoft.Compute

    • virtualMachines
    • disks
  • Microsoft.Network

    • networkInterfaces
    • publicIPAddresses
    • networkSecurityGroups
    • virtualNetworks
  • Microsoft.Storage

    • storageAccounts

Another common example involves moving a virtual network. You may have to move several other resources associated with that virtual network. The move request could require moving public IP addresses, route tables, virtual network gateways, network security groups, and others. In general, a virtual network gateway must always be in the same resource group as its virtual network, they can't be moved separately.

Question: What does the error code "RequestDisallowedByPolicy" mean?

Resource Manager validates your move request before attempting the move. This validation includes checking policies defined on the resources involved in the move. For example, if you're attempting to move a key vault but your organization has a policy to deny the creation of a key vault in the target resource group, validation fails and the move is blocked. The returned error code is RequestDisallowedByPolicy.

For more information about policies, see What is Azure Policy?.

Question: Why can't I move some resources in Azure?

Currently, not all resources in Azure support move. For a list of resources that support move, see Move operation support for resources.

Question: How many resources can I move in a single operation?

When possible, break large moves into separate move operations. Resource Manager immediately returns an error when there are more than 800 resources in a single operation. However, moving less than 800 resources may also fail by timing out.

Question: What is the meaning of the error that a resource isn't in succeeded state?

When you get an error message that indicates a resource can't be moved because it isn't in a succeeded state, it may actually be a dependent resource that is blocking the move. Typically, the error code is MoveCannotProceedWithResourcesNotInSucceededState.

If the source or target resource group contains a virtual network, the states of all dependent resources for the virtual network are checked during the move. The check includes those resources directly and indirectly dependent on the virtual network. If any of those resources are in a failed state, the move is blocked. For example, if a virtual machine that uses the virtual network has failed, the move is blocked. The move is blocked even when the virtual machine isn't one of the resources being moved and isn't in one of the resource groups for the move.

When you receive this error, you have two options. Either move your resources to a resource group that doesn't have a virtual network, or contact support.

Next steps

For a list of which resources support move, see Move operation support for resources.