Terraform Import Bringing Existing Resources Under Management

Not every infrastructure project starts with a blank slate. Sometimes you inherit resources created manually in the cloud console, by a previous tool, or before your team adopted Terraform. The terraform import command brings these existing resources into Terraform's state so you can manage them going forward without destroying and recreating them.

What Import Does

Import reads an existing cloud resource's current state and writes it into Terraform's state file. It does not generate configuration code for you — it only maps an existing resource to a resource block you have already written.

Diagram: Import Flow

Before import:
  Cloud (AWS/Azure): EC2 instance exists  (i-0abc123)
  Terraform state:   (empty — doesn't know about it)
  Your .tf file:     resource "aws_instance" "web" { ... }

After import:
  Cloud (AWS/Azure): EC2 instance exists  (i-0abc123)
  Terraform state:   aws_instance.web → i-0abc123 (now tracked)
  Your .tf file:     resource "aws_instance" "web" { ... } (unchanged)

Next terraform plan:
  Terraform compares state to your .tf file
  Shows any differences between the real resource
  and what your code describes

The Classic Import Workflow (Terraform 1.4 and Earlier)

Step 1: Write the Resource Block

You must first write the resource block in your .tf file. The import command needs somewhere to map the real resource to.

resource "aws_instance" "web" {
  # Arguments will be filled in after import
  # Leave the block minimal for now
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
}

Step 2: Find the Resource ID

Every cloud resource has a unique ID. The Terraform provider documentation for each resource type tells you what the import ID format is.

Resource TypeImport ID FormatExample
aws_instanceInstance IDi-0abc123def456
aws_s3_bucketBucket namemy-bucket-name
aws_security_groupSecurity group IDsg-0abc123
aws_route53_recordZone ID/Name/TypeZ1234_example.com_A

Step 3: Run the Import Command

terraform import RESOURCE_ADDRESS RESOURCE_ID

# Example:
terraform import aws_instance.web i-0abc123def456

Terraform contacts AWS, reads all the attributes of that EC2 instance, and writes them to the state file under aws_instance.web.

Step 4: Run terraform plan and Fix Differences

terraform plan

Terraform now shows a plan comparing your .tf configuration against the imported state. If your code is missing arguments or has wrong values, the plan shows what would change. Update your code until terraform plan shows no changes — that means your code perfectly matches reality.

The Native Import Block (Terraform 1.5+)

Terraform 1.5 introduced a declarative import block — a better alternative to the CLI command. You declare the import in code, which makes it reviewable and repeatable.

import {
  to = aws_instance.web
  id = "i-0abc123def456"
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  # ...
}

Run terraform plan to see what the import will look like, then terraform apply to execute it. After the import succeeds, remove the import block — it has done its job.

Auto-Generating Configuration (Terraform 1.5+)

Terraform 1.5 also introduced the -generate-config-out flag, which automatically writes a .tf configuration file for an imported resource:

# Write an import block with no matching resource block
import {
  to = aws_instance.web
  id = "i-0abc123def456"
}

# Then run:
terraform plan -generate-config-out=generated.tf

Terraform reads every attribute of the real EC2 instance and writes a complete resource "aws_instance" "web" block into generated.tf. Review and clean up the generated file — it will have many attributes set to their current values that you may want to manage through variables instead.

Bulk Import with for_each

When importing multiple similar resources, combine the import block with for_each:

locals {
  servers = {
    web    = "i-0abc111"
    api    = "i-0abc222"
    worker = "i-0abc333"
  }
}

import {
  for_each = local.servers
  to       = aws_instance.app[each.key]
  id       = each.value
}

resource "aws_instance" "app" {
  for_each      = local.servers
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
}

Key Points

  • Terraform import brings existing cloud resources into Terraform state without destroying and recreating them.
  • Import maps a real resource (by its cloud ID) to a resource block in your .tf configuration.
  • After import, run terraform plan and update your code until the plan shows no differences.
  • In Terraform 1.5+, use declarative import blocks in code instead of the CLI command for reviewability.
  • Use terraform plan -generate-config-out=generated.tf to auto-generate configuration for imported resources.

Leave a Comment