Recently I needed to refactor some Terraform configuration, which had grown into quite a large single state file, into smaller separate directories with their own state files.

This is a little bit tricky but the Terraform CLI tool helps a lot.

The first thing is to get the existing single state file JSON:

terraform state pull | tee terraform.tfstate


This should work for any storage backend.

Alternatively you can use gsutil to copy the Terraform state file from a GCS bucket:

gsutil cp gs://your-bucket/your-prefix/terraform.tfstate ./terraform.tfstate


Once you’ve got a local copy of the large single Terraform state file, you can start working with the Terraform CLI tool to extract resources out into separate smaller files.

Extracting a single resource looks like this:

terraform state mv \
-state=terraform.tfstate \
-state-out=extracted.tfstate \
'module.entity-smart-commissioning-status["prod"]'{,}


The {,} on the end is a little Bash trick to repeat that argument, e.g. foobar{,} expands to foobar foobar. This keeps the resource name the same when moving it into the new state file.

You can run that command for each resource that needs extracting, and for several different extracted Terraform state files if that applies in your case.

Once that is done, you can push the trimmed down original state file back to the storage backend with:

terraform state push terraform.tfstate


Again, there is also the alternative of doing this via gsutil to upload the file to a GCP bucket without going via Terraform:

gsutil cp ./terraform.tfstate gs://your-bucket/your-prefix/terraform.tfstate


You can use either of the commands to push the new extracted state files to the correct locations from their respective Terraform directories.