What is an Execution Plan?
An execution plan is Terraform’s proposal for what changes need to be made to bring your infrastructure from its current state to match your configuration. The plan is created duringterraform plan and executed during terraform apply.
A key design tenet of Terraform is that any action with externally-visible side-effects must go through the plan-and-apply workflow. This ensures predictability and enables review before changes are made.Source:
docs/planning-behaviors.mdThe Plan Data Structure
A plan is represented by theplans.Plan struct, which contains:
The plan structure includes both the changes to make (
Changes) and the context in which those changes were planned (PriorState, VariableValues, etc.).Planning Process
The planning process follows these steps, orchestrated bycontext_plan.go:
Refresh State
Read current state of resources from the remote system to detect drift.This produces
PriorState by calling ReadResource on providers.Build Plan Graph
Construct a dependency graph for the plan operation using
PlanGraphBuilder.Walk the Graph
Execute each vertex in dependency order, calling provider
PlanResourceChange for each resource.Collect Changes
Aggregate all planned changes into the
Changes structure.Return Plan
Package everything into a
Plan object.Action Types
Terraform supports several action types for resource instances:| Action | Symbol | Description | When It Occurs |
|---|---|---|---|
| NoOp | No changes needed | Resource matches configuration | |
| Create | + | Create new resource | Resource doesn’t exist in state |
| Read | ↻ | Refresh data source | Data source needs reading |
| Update | ~ | Update in-place | Resource exists but attributes differ |
| Delete | - | Destroy resource | Resource in state but not in config |
| Replace | -/+ or +/- | Delete then create, or create then delete | Resource requires replacement |
plans/action.go
Replace Actions
Replace is a “meta-action” that decomposes into separate Create and Delete operations:- Delete-Before-Create (Default)
- Create-Before-Delete
Default Planning Behavior
When given no special instructions, Terraform’s planning logic (fromdocs/planning-behaviors.md) automatically proposes:
Create
When:- A
resourceblock in configuration has no corresponding resource in state - A
resourceblock’scount/for_eachincludes a new instance key
Delete
When:- A resource in state has no corresponding
resourceblock in configuration - A
resourceblock’scount/for_eachno longer includes an instance key from state
Update
When:- Resource exists in both configuration and state
- Provider detects differences that aren’t just normalization
- Resource is not marked as “tainted”
Replace
When:- Resource exists in both configuration and state
- Resource is marked as “tainted” (previous apply failed)
- Or provider indicates attributes require replacement
Special Planning Behaviors
Terraform supports three categories of special planning behaviors:1. Configuration-Driven Behaviors
Specified in the Terraform configuration by module authors:2. Provider-Driven Behaviors
Activated by providers duringPlanResourceChange:
- Forced replacement - Provider indicates certain attribute changes require replace
- Normalization - Provider returns prior state value instead of config value for equivalent serializations
- Computed values - Provider sets unknown values that will be determined during apply
docs/planning-behaviors.md
3. Single-Run Behaviors
Activated via command-line flags:Resource Instance Change Lifecycle
The full lifecycle of planning and applying a resource change involves multiple provider calls:PlanResourceChange is called twice: once during planning (with potentially unknown config values) and once during apply (with fully known values).Source: docs/resource-instance-change-lifecycle.mdProvider Planning Contracts
When providers implementPlanResourceChange, they must follow strict contracts:
Configuration Values Must Be Preserved
Configuration Values Must Be Preserved
Any attribute that was non-null in configuration must either:
- Preserve the exact configuration value, OR
- Return the prior state value (for normalization only)
Computed Attributes Can Be Set
Computed Attributes Can Be Set
Attributes marked as computed in the schema and null in configuration may be set to any appropriate value, or left unknown.
Known Values Are Promises
Known Values Are Promises
If a planned attribute has a known value, that exact value must appear in the state returned by
ApplyResourceChange.Use unknown values when the final value will be determined during apply.Final Plan Must Match Initial Plan
Final Plan Must Match Initial Plan
When
PlanResourceChange is called the second time during apply:- Known values from initial plan must remain unchanged
- Unknown values may become known or stay unknown
docs/resource-instance-change-lifecycle.md
Plan Files
Plans can be saved to disk for later execution:Plan File Contents
A plan file (ininternal/plans/planfile) contains:
- The complete set of proposed changes
- Prior state snapshots (PrevRunState and PriorState)
- Variable values used during planning
- Provider configurations
- Terraform version information
Drift Detection
Terraform detects drift during the refresh phase:Plan.DriftedResources.
Plan Quality
Plans have a quality indicator (fromplans/quality.go):
- Complete - Plan includes all resources
- Partial - Some resources couldn’t be planned (but plan is still applyable)
- Errored - Planning failed, plan is not applyable
Plan Metadata
Every plan includes metadata:Working with Plans in Code
Creating a plan in Terraform Core:internal/terraform/context_plan.go
Why Plans Matter
Safety
Review changes before applying prevents accidental destruction or misconfiguration.
Predictability
Know exactly what will change, enabling informed decisions.
Audit Trail
Plans can be saved and reviewed later to understand what changed and why.
Automation
Enable automated approval workflows based on plan analysis.
Best Practices
Always Review Plans
Always Review Plans
Never run
terraform apply without first reviewing the plan. Use terraform plan to preview changes.Save Plans for Important Changes
Save Plans for Important Changes
For production changes, save plans to files and review them before applying:
Watch for Unexpected Replaces
Watch for Unexpected Replaces
If Terraform plans to replace resources unexpectedly, investigate why before applying. It may indicate:
- Provider bug
- Incorrect attribute value
- Missing
lifecyclerules
Handle Drift Appropriately
Handle Drift Appropriately
When drift is detected, decide whether to:
- Import the changes into configuration
- Restore the original state
- Accept and ignore the drift (
ignore_changes)
Next Steps
Resource Graph
Learn how Terraform determines the order of operations in a plan
State Management
Understand how state is used during planning