website/docs/intro/migration/multiple-configurations.mdx
This guide addresses the specific challenges of migrating systems built from multiple interdependent Terraform configurations that share data using the terraform_remote_state data source.
If you're migrating a single, standalone Terraform configuration, refer to the Migration Guide instead.
Use this guide if you meet any of the following criteria:
- **Data sharing between root modules** using `terraform_remote_state`
- **Dependencies between root modules** (one root module consumes outputs from the other)
The terraform_remote_state data source allows one configuration to read outputs from another configuration's state file. This creates a dependency relationship between configurations.
For more details, see the terraform_remote_state documentation
Example:
# Configuration A: Creates a VPC
output "vpc_id" {
value = aws_vpc.main.id
}
# Configuration B: Consumes the VPC ID
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "vpc/terraform.tfstate"
}
}
resource "aws_subnet" "main" {
vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
//...
}
In this example, Configuration B depends on Configuration A. Configuration B reads A's state file to get the VPC ID.
When migrating to OpenTofu, the order in which you migrate configurations is critical because:
Before migrating a config, map out your configuration dependencies.
Configuration A (VPC)
↑
|
Configuration B (Subnets)
Configuration B depends on A (B reads A's state).
A
↑
|
+----+----+
| | |
B C D
↑ ↑ ↑
| +----+
| |
| E
| ↑
| |
F |
↑ |
+----+----+
|
G
In this graph:
To create your dependency graph:
terraform_remote_stateCritical principle: Migrate dependent configurations before their dependencies.
OpenTofu maintains state file compatibility with Terraform 1.x, which means:
OpenTofu can read Terraform state files
Terraform may not reliably read OpenTofu state files (especially if OpenTofu-specific features are used)
This compatibility pattern makes bottom-up migration safe:
terraform_remote_state on state from configurations that are still on TerraformFor the complex dependency graph above, the safe migration order is:
Phase 1: Migrate the leaf node (no dependents)
G → (migrate first)
Phase 2: Migrate G's direct dependencies
F, E → (migrate after G)
Phase 3: Continue up the tree
B, C, D → (migrate after F and E)
Phase 4: Migrate the root
A → (migrate last)
If you migrate A first (top-down):
A (OpenTofu) → B, C, D (Terraform)
Configurations B, C, and D (still on Terraform) would try to read state written by A (now on OpenTofu). This could cause issues if:
Bottom-up migration avoids this risk entirely.
Create a visual representation of your configuration dependencies using terraform_remote_state data sources by:
terraform_remote_stateFind configurations that:
These are your starting points for migration.
Before migrating any configuration:
For each leaf configuration:
tofu plantofu applyAfter migrating a configuration, verify that:
terraform plan (or tofu plan if already migrated) on those dependent configsRepeat steps 4-5 for each level of your dependency graph, moving from leaf nodes toward root nodes.
Once all dependent configurations are migrated, migrate the root configurations (those that have no dependencies themselves but are depended upon by others).
If you need to roll back a specific configuration:
terraform init and terraform planThe bottom-up approach makes rollback safer because:
Your configurations may be using different Terraform versions (1.6.x, 1.7.x, 1.8.x).
Recommended approach: Before migrating to OpenTofu, upgrade all configurations to the same Terraform version. This narrows down variables and makes troubleshooting easier if you encounter any issues during migration.
If you encounter issues during migration: