Skip to main content
Naming things is hard, and names change. A bucket called media_files becomes media_store when the team reorganises. A security group called app needs to become api when a second app tier is added. In plain Pulumi, renaming a resource means deleting the old one and creating a new one — which for a production S3 bucket with data, or an RDS instance with a live database, or any stateful resource, is simply not acceptable. The moved block tells Pulumi that the old state key (the old label) maps to the new unit block (the new label), so the rename is recorded as a state operation rather than a destroy-and-recreate. No downtime. No data loss. Just a new name in state.

What you’ll learn

  • How moved renames a resource in Pulumi state without destroying it
  • The from / to syntax and what each references
  • When to remove the moved block after applying

Why this matters

Without moved, renaming a unit block label causes Pulumi to destroy the old resource and create a new one. For stateful resources — databases, storage buckets, load balancers — this is destructive. moved makes refactoring safe.

The source code

# New name — this unit block replaces the old "media_files" block.
# The old "media_files" unit block has been removed from .iac.
unit "aws_s3_bucket_v2" "media_store" {
  bucket = "myapp-media"
}

How it works

1

ubx compiles moved to a Pulumi alias

The moved block compiles to a aliases option on the to resource’s Pulumi constructor. The alias is the full Pulumi URN of the old resource (derived from the from reference). Pulumi uses aliases to match existing state entries to new resource declarations.
2

Pulumi recognises the alias and skips destroy

At apply time, Pulumi looks up the old URN in state, finds a matching alias on the new resource, and records the rename as a state update rather than a destroy-and-create. The cloud resource is unchanged — only the state entry is updated.
3

Remove the moved block after the first apply

Once the rename is in state, the moved block serves no purpose. Leaving it in place doesn’t cause errors, but it adds a stale alias to every subsequent apply. Remove it after confirming the apply succeeded.

What ubx generates

// Generated by ubx — do not edit
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// alias generated from the moved block — tells Pulumi the old state key
const mediaStore = new aws.s3.BucketV2("media_store", {
    bucket: "myapp-media",
}, {
    aliases: [{ name: "media_files" }],  // generated from moved block
});

export const bucketName = mediaStore.bucket;

Common mistakes

from can reference a block that no longer exists in the .iac files — this is intentional and expected. The old unit "aws_s3_bucket_v2" "media_files" block is removed when the rename happens; the moved block’s from is a bare reference that tells ubx where to find the old URN in state, not a reference to a live block.
moved works for any resource type, not just S3 buckets — RDS instances, security groups, EC2 instances, IAM roles. Any time you rename a unit block label and the resource shouldn’t be destroyed, add a moved block before applying.

Run it

ubx validate   # confirms from/to references are valid
ubx plan       # shows the rename as a state update, not destroy + create
ubx apply      # renames in state — cloud resource is unchanged
# After successful apply: remove the moved block

What you learned

moved renames a resource in Pulumi state without destroying or recreating the cloud resource
from references the old label (the block no longer needs to exist); to references the new unit block
Remove the moved block after the first successful apply

Next steps

data source lookup

Query existing cloud resources without managing them

moved block reference

Full moved block syntax