Pulumi infrastructure-as-code skills for Claude Code with ESC, OIDC, and cloud provider best practices.
99
Quality
99%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Complete reference for Pulumi state operations, recovery patterns, and best practices.
Pulumi state tracks the mapping between your program's resources and the actual cloud resources. State is stored in a backend (Pulumi Cloud, S3, Azure Blob, GCS, or local filesystem).
Key concepts:
Remove a resource from state without deleting the actual cloud resource.
# Delete resource from state (keeps cloud resource)
pulumi state delete 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::my-bucket'
# Delete with confirmation skip
pulumi state delete 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::my-bucket' --yes
# Force delete even if protected
pulumi state delete 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::my-bucket' --force
# Delete from specific stack
pulumi state delete --stack prod 'urn:pulumi:prod::myproject::aws:s3/bucket:Bucket::my-bucket'Use cases:
Move resources between stacks.
# Move resource to another stack
pulumi state move \
--source dev \
--dest prod \
'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::my-bucket'
# Move multiple resources
pulumi state move \
--source dev \
--dest prod \
'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::bucket-1' \
'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::bucket-2'
# Move with confirmation skip
pulumi state move --source dev --dest prod 'urn:...' --yesImportant considerations:
Rename a resource in state.
# Rename resource
pulumi state rename \
'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::old-name' \
'new-name'
# Rename in specific stack
pulumi state rename --stack dev 'urn:pulumi:dev::...' 'new-name'Use cases:
Prevent accidental deletion of resources.
# Protect resource from deletion
pulumi state protect 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::critical-bucket'
# Unprotect resource
pulumi state unprotect 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::critical-bucket'
# Check protection status (in state export)
pulumi stack export | jq '.deployment.resources[] | select(.protect == true)'Protected resources:
pulumi destroypulumi preview with protection indicatorMark resources for replacement.
# Mark resource for replacement on next update
pulumi state taint 'urn:pulumi:dev::myproject::aws:ec2/instance:Instance::web-server'
# Remove taint (cancel scheduled replacement)
pulumi state untaint 'urn:pulumi:dev::myproject::aws:ec2/instance:Instance::web-server'Use cases:
Repair invalid state checkpoints.
# Repair state
pulumi state repair
# Repair specific stack
pulumi state repair --stack devWhat it repairs:
# Export current stack state
pulumi stack export --file state-backup.json
# Export specific stack
pulumi stack export --stack prod --file prod-backup.json
# Export with version
pulumi stack export --version 42 --file state-v42.json# Import state from backup
pulumi stack import --file state-backup.json
# Import to specific stack
pulumi stack import --stack dev --file state-backup.json# 1. Export from source backend
pulumi login https://api.pulumi.com
pulumi stack export --stack myorg/myproject/prod --file state.json
# 2. Login to target backend
pulumi login s3://my-state-bucket
# 3. Create stack and import
pulumi stack init prod
pulumi stack import --file state.jsonWhen someone deletes a resource directly in the cloud console:
# Option 1: Refresh to sync state (removes from state)
pulumi refresh --yes
# Option 2: Delete from state manually (if refresh fails)
pulumi state delete 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::deleted-bucket'
# Then run up to recreate
pulumi up --yesWhen an update was interrupted and left pending operations:
# View pending operations
pulumi stack export | jq '.deployment.pending_operations'
# Option 1: Refresh with clear pending
pulumi refresh --clear-pending-creates --yes
# Option 2: Cancel and retry
pulumi cancel --yes
pulumi refresh --yes
pulumi up --yes
# Option 3: Manual state repair
pulumi state repair
pulumi refresh --yesWhen you need to adopt existing resources:
# Option 1: Import the resource
pulumi import aws:s3/bucket:Bucket my-bucket my-existing-bucket-id
# Option 2: Refresh to detect (if resource is in code)
pulumi refresh --yesWhen state becomes corrupted:
# 1. Try automatic repair
pulumi state repair
# 2. If that fails, check for backups
pulumi stack history
pulumi stack export --version <previous-good-version> --file backup.json
# 3. Import the backup
pulumi stack import --file backup.json
# 4. Refresh to sync with reality
pulumi refresh --yesComplete workflow for refactoring resources across stacks:
# 1. Export source stack state
pulumi stack export --stack source-stack --file source.json
# 2. Identify resource URN
cat source.json | jq '.deployment.resources[] | select(.urn | contains("my-resource"))'
# 3. Move resource
pulumi state move \
--source source-stack \
--dest target-stack \
'urn:pulumi:source-stack::myproject::aws:s3/bucket:Bucket::my-bucket'
# 4. Update code in both stacks
# - Remove resource from source stack code
# - Add resource to target stack code (with same URN name)
# 5. Verify both stacks
pulumi preview --stack source-stack
pulumi preview --stack target-stack# 1. Get current URN
pulumi stack export | jq '.deployment.resources[].urn' | grep my-resource
# 2. Rename in state
pulumi state rename 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::old-name' 'new-name'
# 3. Update code to match new name
# Change: new aws.s3.Bucket("old-name", {...})
# To: new aws.s3.Bucket("new-name", {...})
# 4. Preview to verify no changes
pulumi preview# View all resources
pulumi stack export | jq '.deployment.resources[]'
# View specific resource
pulumi stack export | jq '.deployment.resources[] | select(.urn | contains("my-bucket"))'
# View resource outputs
pulumi stack export | jq '.deployment.resources[] | select(.urn | contains("my-bucket")) | .outputs'
# View resource inputs
pulumi stack export | jq '.deployment.resources[] | select(.urn | contains("my-bucket")) | .inputs'
# Count resources by type
pulumi stack export | jq '[.deployment.resources[].type] | group_by(.) | map({type: .[0], count: length})'
# Find protected resources
pulumi stack export | jq '.deployment.resources[] | select(.protect == true) | .urn'
# Find pending operations
pulumi stack export | jq '.deployment.pending_operations'URNs follow this format:
urn:pulumi:<stack>::<project>::<type>::<name>Example:
urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::my-bucket
│ │ │ │
stack project resource type resource name# Before major operations, always backup
pulumi stack export --file "backup-$(date +%Y%m%d-%H%M%S).json"
# Automate in CI/CD
pulumi stack export --file "state-${GITHUB_SHA}.json"
aws s3 cp "state-${GITHUB_SHA}.json" "s3://my-backups/pulumi/"--yes carefully - prefer interactive confirmation# Protect production databases
pulumi state protect 'urn:pulumi:prod::myproject::aws:rds/instance:Instance::prod-db'
# Protect stateful resources
pulumi state protect 'urn:pulumi:prod::myproject::aws:efs/fileSystem:FileSystem::shared-storage'Pulumi Cloud and most backends support state locking:
# S3 backend with locking
pulumi login 's3://my-bucket?region=us-west-2&awssdk=v2'# Resource exists in cloud but not state - import it
pulumi import aws:s3/bucket:Bucket my-bucket existing-bucket-id
# Or delete from cloud and let Pulumi recreate
aws s3 rb s3://existing-bucket-id --force
pulumi up --yes# Resource was deleted outside Pulumi
pulumi state delete 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::missing-bucket'# Clear pending operations
pulumi refresh --clear-pending-creates --yes
# Or cancel and retry
pulumi cancel --yes
pulumi state repair# Check state size
pulumi stack export | wc -c
# Consider splitting into multiple stacks
# Use stack references for dependencies