Crisp answer: Plan shows what will change without changing anything. Apply executes the changes. Import brings existing infrastructure under Terraform management without recreating it.
terraform plan:
terraform plan # Standard plan
terraform plan -out=tfplan # Save plan to file (use in CI)
terraform plan -target=aws_instance.web # Plan only one resource
terraform plan -refresh=false # Skip refreshing state from AWS (faster, less accurate)
terraform plan -var-file=prod.tfvars
The plan output shows three categories:
# aws_instance.web will be created (+)
# aws_security_group.app will be updated in-place (~)
# aws_subnet.old will be destroyed (-)
# aws_instance.replaced must be replaced (-/+) ← destroy then create
-/+ (replace) is the dangerous one. It means Terraform will destroy the
resource and recreate it. This happens when you change an immutable attribute
(like an EC2 AMI, RDS engine version, or EKS cluster name). Check for
-/+ before every apply on production.
terraform apply:
terraform apply # Plan + prompt for confirmation
terraform apply -auto-approve # Skip confirmation (use in CI, with caution)
terraform apply tfplan # Apply a saved plan (no re-planning, deterministic)
terraform apply -target=module.vpc # Apply only specific resources
Best practice in CI: always plan -out=tfplan in one step, then apply tfplan
in a separate step. This ensures what you reviewed is exactly what gets applied.
terraform import:
Brings an existing resource (created manually or by another tool) into Terraform state without recreating it:
# Import an existing EC2 instance:
terraform import aws_instance.web i-0abc123def456
# Import an S3 bucket:
terraform import aws_s3_bucket.state my-terraform-state
# Import an EKS cluster:
terraform import aws_eks_cluster.main my-cluster
After import, the resource is in state but you must write the matching .tf
config yourself. Run terraform plan after import — if config and reality
match, the plan should show no changes.
terraform refresh:
Updates state to match the real world without changing anything:
terraform refresh # deprecated in favour of:
terraform apply -refresh-only # shows what would change in state, applies on confirmation
Use this when someone made a manual change in the console and you want state to reflect reality before your next plan.
What to say in the interview:
"Plan is a dry run that shows what will change. The key thing I look for is any minus-slash-plus which means a resource will be destroyed and recreated — that needs careful review on production. Apply executes the plan. In CI I always save the plan to a file with -out and apply that exact file, so there's no drift between what was reviewed and what ran. Import is for onboarding existing infrastructure — it adds the resource to state so Terraform can manage it going forward, but you still need to write the matching HCL config."