Sometimes you need to move the state of a site to another: switch from local to remote state, change buckets, reorganize your project, or merge configurations. State migration is a delicate but common operation, and it’s important to know how to do it properly to avoid losing or corrupting your “source of truth.” In this subchapter, we’ll see how to migrate state safely.
Why Migrate State
Remember that the state is the record of what infrastructure exists (Chapter 11). There are several real situations where you need to move it:
- From local to remote: you started with local state (on your laptop) and now want to move it to a shared S3 backend (subchapter 20.1) to work as a team. This is the most common case.
- Backend change: you move the state from one bucket to another, or from one system to another (for example, to Terraform Cloud, Chapter 22).
- Project reorganization: you split a large project into several smaller ones, or merge several into one, which involves moving resources between states.
Migrating from Local to Remote (the Most Common)
This is the most frequent migration and, fortunately, Terraform makes it almost automatic. The process:
1. You have LOCAL state (terraform.tfstate in your folder) 2. ADD the remote backend configuration (backend "s3" block) 3. Run: terraform init 4. Terraform detects the change and asks: "Do you want to migrate the existing state to the new backend?" → yes 5. Done! The state now lives in S3
When you run terraform init after adding the backend, Terraform is smart enough to realize you have a local state and offers to copy it to the new destination:
Initializing the backend... Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "local" backend to the newly configured "s3" backend. ... Enter "yes" to copy and "no" to start with an empty state.
You answer yes and Terraform copies the state to the remote backend. From then on, it works from S3.
Changing from One Remote Backend to Another
If you already have a remote backend and want to change it (for example, another bucket), the process is similar:
1. CHANGE the backend configuration (new bucket, new path...) 2. Run: terraform init -migrate-state 3. Terraform copies the state from the old backend to the new one
The -migrate-state option explicitly tells Terraform that you want to move the state to the new backend, not start from scratch.
Moving Specific Resources Between States
Sometimes you don’t want to move all the state, but specific resources from one project to another (for example, when splitting a large project). For this, there’s the terraform state mv command, which relocates a resource within the state or to another:
This tells Terraform: “this resource now lives elsewhere in the state, but it’s the same real resource; don’t destroy or recreate it, just update its record.” It’s very useful when refactoring (for example, when moving loose resources into a module, Chapter 18).
Why
state mvmatters: without it, if you reorganize your code and Terraform “loses sight” of a resource, it might think it no longer exists and want to destroy it and create a new one.state mvavoids that mess: you tell it “it’s the same, it just changed name/location in the code.”
Golden Rules for Safe Migration
State migration touches your “source of truth,” so caution is essential. Always follow these rules:
- Make a Backup BEFORE
Before any migration, save a copy of the current state. If something goes wrong, you can restore it. If your S3 bucket has versioning enabled (subchapter 20.1), you already have that history, but an extra manual copy never hurts.
- Notify the Team and Make Sure No One Else Is Working
During migration, no one else should be running Terraform on that state. Coordinate with your team (remember the locking from subchapter 20.2: migration also requires the state not to be in use).
- Verify with Plan After Migrating
After migration, run terraform plan. If the migration was correct, the plan should show “no changes” (No changes): this confirms that the new state reflects exactly the real infrastructure, without having lost or altered anything.
After migrating: terraform plan → "No changes. Your infrastructure matches the configuration." ✓ perfect → if it shows unexpected changes ⚠️ something went wrong, investigate before applying
- Never Edit the State by Hand
The state file is a JSON, but do not edit it manually except in extreme emergencies and only if you really know what you’re doing. Always use Terraform commands (state mv, state rm, init -migrate-state), which know its internal structure and prevent corruption.
What You Should Remember
- Migrating state (moving it elsewhere) is necessary when switching from local to remote, changing backend, or reorganizing the project.
- Local → remote: add the
backendblock and runterraform init; Terraform detects the local state and offers to copy it (you answeryes). It’s almost automatic. - Remote → another remote: change the configuration and use
terraform init -migrate-state. - To move specific resources within the state (when refactoring), use
terraform state mv, which prevents Terraform from destroying and recreating a resource that only changed location in the code. - Golden rules: make a backup first, notify the team (no one else working), verify with
planafter (should say “no changes”), and never edit the state by hand.
In the last subchapter of the chapter, we’ll see a very related and very useful operation: terraform import, to bring into the state resources that already exist in AWS but that Terraform does not yet manage.
Cloud, AWS & Terraform — From Zero to Expert
Chapter 1 · What is cloud computing
- 1.1 The traditional client-server model
- 1.2 Problems the cloud came to solve
- 1.3 On-premise vs cloud vs hybrid
- 1.4 The three service models: IaaS, PaaS, SaaS
- 1.5 The five pillars of cloud (according to NIST)
- 1.6 Real advantages: elasticity, pay-as-you-go, global availability
Chapter 2 · The cloud market and major providers
- 2.1 AWS, Azure and GCP: differences and market share
- 2.2 Why learn AWS first
- 2.3 Concepts that are universal among providers
Chapter 3 · Regions, availability zones and edge
- 3.1 What is an AWS region and how to choose it
- 3.2 Availability Zones: high availability by design
- 3.3 Edge locations and CloudFront
- 3.4 Latency, resilience and data sovereignty
Chapter 4 · Compute: EC2
- 4.1 Instances: types, families and when to choose each
- 4.2 AMIs, key pairs and Security Groups
- 4.3 Instance lifecycle
- 4.4 Elastic IPs and Placement Groups
- 4.5 Savings Plans vs Reserved vs On-Demand vs Spot
Chapter 5 · Storage: S3
- 5.1 Buckets, objects and keys
- 5.2 Storage classes (Standard, IA, Glacier…)
- 5.3 Versioning and object lifecycle
- 5.4 Bucket policies and ACLs
- 5.5 Static website hosting
Chapter 6 · Networking: VPC
- 6.1 What is a VPC and why you need it
- 6.2 Public and private subnets
- 6.3 Internet Gateway and NAT Gateway
- 6.4 Route Tables and Network ACLs
- 6.5 VPC Peering and endpoints
Chapter 7 · Identity and access: IAM
- 7.1 Users, groups, roles and policies
- 7.2 The principle of least privilege
- 7.3 Identity-based vs resource-based policies
- 7.4 MFA and temporary credentials (STS)
- 7.5 IAM security best practices
Chapter 8 · Managed databases
- 8.1 RDS: engines, Multi-AZ and read replicas
- 8.2 Aurora and its advantages over vanilla RDS
- 8.3 DynamoDB: key-value / document model
- 8.4 ElastiCache for in-memory cache
- 8.5 When to use each type of database
Chapter 9 · Why Infrastructure as Code
- 9.1 Problems with manual provisioning
- 9.2 Declarative vs imperative IaC
- 9.3 Terraform vs CloudFormation vs Pulumi vs CDK
- 9.4 The plan → apply → destroy cycle
Chapter 10 · HCL: the Terraform language
- 10.1 Resource, variable, output, locals blocks
- 10.2 Data types: string, number, bool, list, map, object
- 10.3 Expressions, references and built-in functions
- 10.4 Conditionals and loops (count, for_each, for)
Chapter 11 · Providers and state
- 11.1 How the AWS provider works
- 11.2 The terraform.tfstate file and its importance
- 11.3 Local state vs remote state (S3 + DynamoDB)
- 11.4 Essential commands: init, plan, apply, destroy, fmt, validate
Chapter 12 · Your first real infrastructure in Terraform
- 12.1 Create a VPC with subnets from scratch
- 12.2 Launch a public EC2 instance
- 12.3 Associate a Security Group and an Elastic IP
- 12.4 Outputs and references between resources
- 12.5 Team workflow: PR review of plans
Chapter 13 · Load balancing and auto scaling
- 13.1 Application Load Balancer vs Network Load Balancer
- 13.2 Target Groups, listeners and rules
- 13.3 Auto Scaling Groups: policies and metrics
- 13.4 Warm pools and lifecycle hooks
Chapter 14 · Serverless with Lambda
- 14.1 The Lambda execution model
- 14.2 Triggers: API Gateway, S3, DynamoDB Streams, SQS
- 14.3 Dependency management and layers
- 14.4 Cold starts and strategies to reduce them
- 14.5 Limits and anti-patterns
Chapter 15 · Messaging and events
- 15.1 SQS: standard vs FIFO queues, DLQ
- 15.2 SNS: topics, subscriptions, fan-out
- 15.3 EventBridge: event buses and rules
- 15.4 Patterns: pub/sub, decoupling, saga
Chapter 16 · Content delivery and DNS
- 16.1 Route 53: record types and routing policies
- 16.2 CloudFront: distributions, caches and origins
- 16.3 ACM: free SSL/TLS certificates
- 16.4 WAF integrated with CloudFront
Chapter 17 · Containers on AWS
- 17.1 Docker: quick review of key concepts
- 17.2 ECR: private image registry
- 17.3 ECS: task definitions, services, Fargate vs EC2
- 17.4 EKS: when Kubernetes and when not
Chapter 18 · Modules: reuse and composition
- 18.1 Anatomy of a Terraform module
- 18.2 Input variables, outputs and dependencies
- 18.3 Local modules vs Terraform Registry modules
- 18.4 Module versioning with Git tags
- 18.5 Design of generic vs domain-specific modules
Chapter 19 · Workspaces and environment management
- 19.1 Terraform workspaces: use cases and limitations
- 19.2 Directory strategy per environment (dev/stg/prod)
- 19.3 Terragrunt: DRY for environment configurations
- 19.4 Environment variables and .tfvars files
Chapter 20 · Remote backends and locking
- 20.1 Configure S3 + DynamoDB as backend
- 20.2 State locking: avoiding team corruption
- 20.3 State migration between backends
- 20.4 terraform import: bring existing resources into state
Chapter 21 · Infrastructure testing
- 21.1 Terraform validate and fmt in CI
- 21.2 Checkov and tfsec: static security analysis
- 21.3 Terratest: integration tests in Go
- 21.4 Contract testing between modules
Chapter 22 · Terraform in CI/CD
- 22.1 Basic pipeline: lint → plan → apply in GitHub Actions
- 22.2 Atlantis: GitOps for Terraform
- 22.3 Terraform Cloud / HCP Terraform
- 22.4 Drift detection and automatic reconciliation
Chapter 23 · Defense in depth
- 23.1 AWS Organizations and Service Control Policies
- 23.2 AWS Config: continuous compliance
- 23.3 GuardDuty: threat detection
- 23.4 Security Hub: centralized view
- 23.5 KMS: key management and rotation
- 23.6 Secrets Manager vs Parameter Store
Chapter 24 · Observability: logs, metrics and traces
- 24.1 CloudWatch Logs, metrics and alarms
- 24.2 CloudWatch Dashboards and Contributor Insights
- 24.3 X-Ray: distributed tracing
- 24.4 OpenTelemetry on AWS
- 24.5 Managed Grafana and Managed Prometheus
Chapter 25 · Cost optimization
- 25.1 AWS Cost Explorer and budgets with alerts
- 25.2 Trusted Advisor and Compute Optimizer
- 25.3 Rightsizing: how to detect overprovisioning
- 25.4 Savings Plans vs Reserved Instances: strategic decision
- 25.5 FinOps: culture and processes to control spending
Chapter 26 · High availability and disaster recovery
- 26.1 RTO and RPO: defining objectives
- 26.2 Strategies: backup/restore, pilot light, warm standby, multi-site
- 26.3 Route 53 health checks and automatic failover
- 26.4 AWS Backup: centralized backup policy
Chapter 27 · AWS Well-Architected Framework
- 27.1 The six pillars: operational excellence, security, reliability, performance efficiency, cost optimization, sustainability
- 27.2 Well-Architected Tool: formal reviews
- 27.3 How to apply the framework in design decisions
Chapter 28 · Serverless architectures at scale
- 28.1 Event-driven architecture with Lambda + EventBridge
- 28.2 Saga pattern for distributed transactions
- 28.3 Step Functions: orchestration of complex workflows
- 28.4 Lambda@Edge and CloudFront Functions
Chapter 29 · Data platforms on AWS
- 29.1 Data Lake with S3, Glue and Athena
- 29.2 Kinesis Data Streams and Firehose for streaming
- 29.3 Redshift: data warehousing at scale
- 29.4 Lake Formation: data governance
Chapter 30 · Multi-account and landing zones
- 30.1 Why separate workloads into different accounts
- 30.2 AWS Control Tower and Account Factory
- 30.3 Centralized log and security management
- 30.4 Terraform at multi-account scale with shared modules
Chapter 31 · Platform Engineering and Internal Developer Platform
- 31.1 Golden paths and abstractions over Terraform
- 31.2 AWS Service Catalog
- 31.3 Backstage as a developer portal
- 31.4 Terraform modules as internal product
Chapter 32 · Relevant AWS certifications
- 32.1 Cloud Practitioner: is it worth it?
- 32.2 Solutions Architect Associate → Professional
- 32.3 DevOps Engineer Professional
- 32.4 Specialty: Security, Database, Networking
- 32.5 HashiCorp Terraform Associate
Chapter 33 · Projects to consolidate what you've learned
- 33.1 Project 1: serverless blog (S3 + CloudFront + Lambda + DynamoDB)
- 33.2 Project 2: REST API with ECS Fargate + RDS + ALB
- 33.3 Project 3: data platform with Glue + Athena + Redshift
- 33.4 Project 4: multi-account landing zone with Terraform and Control Tower
