Pulumi State & Backends

Medium22 min read

Understanding State

Why State & Backends Matter

The Problem: Pulumi needs to know what infrastructure already exists to determine what to create, update, or delete. Without state, every deployment would try to recreate everything.

The Solution: Pulumi maintains a state file that records the mapping between your program's resources and the actual cloud resources, enabling incremental updates.

Real Impact: Proper state management enables team collaboration, prevents conflicts, and ensures infrastructure changes are safe and predictable.

Real-World Analogy

Think of state like an inventory management system:

  • State File = The inventory database recording everything in the warehouse
  • Backend = Where the inventory database is stored (local, cloud, shared drive)
  • Locking = The "checked out" sign preventing two people from editing at once
  • Import = Adding existing items to the inventory that weren't tracked before
  • Refresh = Walking the warehouse to verify inventory matches reality

What State Tracks

Resource Mapping

Maps logical resource names in your code to physical resource IDs in the cloud (e.g., "my-bucket" to "my-bucket-a1b2c3d").

Input Values

Records the input values used to create each resource, enabling Pulumi to detect what changed between deployments.

Output Values

Stores the output values from each resource, including computed values like ARNs, IPs, and endpoints.

Dependencies

Tracks the dependency graph between resources so operations happen in the correct order.

Pulumi Cloud Backend

pulumi-cloud.sh
# Login to Pulumi Cloud (default)
pulumi login

# Login to a specific Pulumi Cloud organization
pulumi login https://app.pulumi.com

# Check current backend
pulumi whoami -v

# View stack in Pulumi Cloud console
pulumi console

Self-Managed Backends

State Backend Options
Pulumi State Pulumi Cloud Managed, Teams, RBAC AWS S3 s3://bucket/prefix Azure Blob azblob://container Google GCS gs://bucket/prefix Local Filesystem
self-managed-backends.sh
# Use local filesystem backend
pulumi login --local

# Use AWS S3 backend
pulumi login s3://my-pulumi-state-bucket

# Use Azure Blob Storage backend
pulumi login azblob://my-state-container

# Use Google Cloud Storage backend
pulumi login gs://my-pulumi-state-bucket

# Use S3-compatible storage (MinIO, etc.)
pulumi login "s3://state?endpoint=minio.example.com&disableSSL=true&s3ForcePathStyle=true"

State Management

state-operations.sh
# Refresh state to match actual cloud resources
pulumi refresh

# View resources in state
pulumi stack --show-urns

# Delete a resource from state (without deleting cloud resource)
pulumi state delete 'urn:pulumi:dev::myproject::aws:s3/bucket:Bucket::my-bucket'

# Rename a resource in state
pulumi state rename 'old-urn' 'new-name'

# Unprotect a protected resource
pulumi state unprotect 'urn:pulumi:dev::myproject::aws:rds/instance:Instance::prod-db'

Import & Export

import-resources.sh
# Import an existing AWS resource into Pulumi state
pulumi import aws:s3/bucket:Bucket my-bucket my-existing-bucket-name

# Export state to a file
pulumi stack export --file state.json

# Import state from a file
pulumi stack import --file state.json

# Import with code generation
pulumi import aws:ec2/vpc:Vpc main-vpc vpc-0123456789abcdef0 --out index.ts

Common Pitfall

Problem: Two team members running pulumi up simultaneously against the same stack can cause state corruption.

Solution: Pulumi Cloud and self-managed backends with locking (S3 + DynamoDB) prevent concurrent modifications. Always use a backend with locking enabled for team environments.

Quick Reference

State & Backend Commands

CommandDescriptionExample
pulumi loginSet the backendpulumi login s3://my-bucket
pulumi refreshSync state with cloudpulumi refresh --yes
pulumi importImport existing resourcepulumi import aws:s3/bucket:Bucket name id
pulumi stack exportExport state to filepulumi stack export --file s.json
pulumi stack importImport state from filepulumi stack import --file s.json
pulumi state deleteRemove from state onlypulumi state delete 'urn:...'
pulumi whoami -vShow current backendpulumi whoami -v