Terraform State vs. Azure Resource Reality - Behavior Matrix


Quick decision tree (what to do)

  • Have resource in Azure but not in state? → terraform import (Row 4, 8, 13).
  • Have resource in state but not in config (and you want to keep it in Azure)? → terraform state rm (Row 6).
  • Renamed/moved resources in code? → terraform state mv to map old address to new (Row 14–15).
  • Portal edits conflict with .tf? → Let TF overwrite, or add ignore_changes for specific fields (Row 2, 10–11).
  • Plan wants to destroy & recreate but you need continuity? → Check if the change really requires replace; if yes, consider create_before_destroy (when supported), or a migration strategy (Row 9).




#

.tf declares resource?

In state?

Exists in Azure?

Situation / Drift

terraform plan shows

apply result

Typical fix / notes

1

No drift

No changes

N/A

Happy path.

2


(props changed in portal)

Property drift

Update in-place (change block)

Terraform updates Azure to match .tf

Or use lifecycle { ignore_changes = [...] } if portal edits are intentional.

3

Resource missing in Azure

Create (sometimes “replace”)

Terraform recreates resource

If it shouldn’t be recreated, stop and investigate why it disappeared.

4

Unmanaged existing (no state)

Create → will fail (“already exists”)

Error, nothing changed

Import first: terraform import <addr> <id>, then re-plan.

5

New resource

Create

Resource created

Normal create.

6

Orphan in config (still in state & Azure)

Destroy

Terraform deletes from Azure

If you want to keep it but stop managing: use terraform state rm <addr> (removes from state only).

7

Ghost in state (stale state)

Destroy (no remote object, may show replace/destroy)

State entry removed

Safer: terraform state rm <addr> to clean state without trying to destroy.

8

Fully unmanaged (not in config or state)

No-op (Terraform ignores it)

N/A

Either import it to manage, or leave it unmanaged. Consider drift detectors outside TF.

9


(but prop requires replace)

Replace drift (e.g., storage account name, SKU that forces new)

-/+ (destroy & create)

Recreates resource (may cause downtime)

Plan carefully; use create_before_destroy if supported, or schedule a window.

10


(minor portal-only tag drift)

Minor drift

Update (tags)

Tags synced to .tf

If portal is the source of truth for some fields, add ignore_changes.

11


(portal added extra sub-resource)

Partial drift (e.g., extra NSG rule)

Remove/alter sub-resources

Terraform reconciles to match .tf

Import/manage those sub-resources explicitly if you want to keep them.

12


(remote recreated manually with diff ID)

ID drift (state points to non-existent)

Create (new)

New resource created

If Azure has a different object you want: import that instead and remove stale state if needed.

13


(different name than .tf)

Name mismatch

Create → may fail (name taken)

Error

Align names, or import and then refactor .tf with terraform state mv if renaming addresses.

14


(renamed addr)


(old addr)

Address drift (resource moved in code)

Create new + destroy old

Replace (even if same real resource)

Use terraform state mv <old> <new> to avoid churn.

15


(module refactor)


(pre-refactor)

Module/addressing drift

Often large create/destroy plan

Potentially destructive

Map old→new with a series of state mv commands before applying.

16

Nothing anywhere

No-op

N/A

Empty case.

Comments

Popular posts from this blog

KB: Azure ACA Container fails to start (no User Assigned or Delegated Managed Identity found for specified ClientId)

Electron Process Execution Failure with FSLogix

KB:RMM VS DEX (Remote Monitoring Management vs Digital Employee Experience)