terraform apply is the command that converts declarative configuration files into running infrastructure. While the conceptual model is straightforward—read the desired state, compare it to the actual state, and make changes—the operational reality is significantly more complex. It is the command most likely to surprise an engineer or an automation pipeline. Executed without careful consideration of flags, environment context, and state locking, terraform apply can create unintended resources, modify production environments accidentally, or leave the Terraform state in a partially updated, inconsistent mess that requires extensive manual cleanup. Understanding the granular differences between interactive execution and automated application, alongside the specific behavioral implications of every available flag, is essential for safe infrastructure management.
This technical deep dive covers the mechanics of terraform apply, distinguishes between automatic and saved plan modes, and provides a comprehensive analysis of every major flag, including -auto-approve, -target, -replace, -destroy, -invoke, -json, and others. It also addresses the specific challenges of applying infrastructure in CI/CD environments and outlines strategies for recovering from failed applications.
Core Functionality and Workflow Position
The terraform apply command is a fundamental part of the Terraform Infrastructure-as-Code (IaC) workflow. Its primary function is to propagate changes specified in code to real-world infrastructure. It executes planned actions, creating, updating, or deleting resources to match the new state outlined in the IaC configuration. Before making any actual changes, terraform apply generates an execution plan for review, ensuring transparency and control. This plan outlines the discrepancies between the current infrastructure state and the desired state defined in the code, identifying resources that need to be created, updated, or deleted.
Terraform provisions infrastructure through a strict sequence of steps. First, terraform init initializes the working directory by installing necessary plugins and providers, setting up the backend, and initializing modules. Second, terraform plan creates an execution plan by comparing the desired state defined in the configuration with the actual state of the infrastructure, outputting the required changes. Finally, terraform apply executes these changes to reach the new state. When terraform apply is run without arguments, it prompts Terraform to create a plan and apply it in a single step. This combined action is convenient for local development but requires caution in shared or production environments.
Execution Modes: Automatic Plan vs. Saved Plan
The behavior of terraform apply differs significantly depending on whether the user passes the filename of a previously saved plan file. There are two distinct modes of operation: Automatic Plan Mode and Saved Plan Mode.
Automatic Plan Mode
In the default case, with no saved plan file provided, terraform apply operates in Automatic Plan Mode. In this mode, terraform apply creates its own plan of action in the same manner that terraform plan would. Terraform then proposes this plan to the user and prompts for approval before taking the described actions. This prompt ensures that the human operator reviews the proposed changes before they are executed. The prompt can be waived by using the -auto-approve option, which bypasses the confirmation step and executes the plan immediately. This mode is typical for interactive, local development workflows where immediate feedback and manual review are preferred.
Saved Plan Mode
The second mode is Saved Plan Mode, which is primarily intended for automation and CI/CD environments. If a user passes the filename of a previously saved plan file (created earlier with terraform plan -out=...), terraform apply performs exactly the steps specified by that plan file. In this mode, Terraform applies the changes without any confirmation prompt. This two-step workflow is critical for decoupling the planning phase from the execution phase. It allows for a "review then apply" workflow where the plan is generated and saved in one stage, reviewed by a human or a gatekeeper in a second stage, and then applied in a third stage. This ensures that the exact changes reviewed are the ones executed, preventing drift between the plan and the apply due to changes in the environment or configuration files between the two steps.
Flag Reference and Behavioral Analysis
Terraform provides a suite of flags to modify the behavior of terraform apply. Each flag serves a specific purpose, ranging from input handling to resource targeting and state management. The table below summarizes the primary flags, their syntax, and their functional impact.
| Flag | Syntax | Description and Use Case |
|---|---|---|
-auto-approve |
terraform apply -auto-approve |
Waives the confirmation prompt. Executes the plan immediately without user interaction. |
-var |
terraform apply -var="key=value" |
Passes a specific variable value to the configuration during the apply operation. |
-var-file |
terraform apply -var-file="file.tfvars" |
Applies infrastructure changes using variable values from a specified .tfvars file. |
-target |
terraform apply -target="resource" |
Limits the apply operation to specific resources or modules. |
-lock=false |
terraform apply -lock=false |
Disables state locking. Dangerous; allows concurrent operations on the same workspace. |
-parallelism |
terraform apply -parallelism=<n> |
Limits the number of concurrent operations. Useful for avoiding cloud provider rate limits. |
-compact-warnings |
terraform apply -compact-warnings |
Condenses warning output into a more concise format for improved readability. |
-input=false |
terraform apply -input=false |
Disables interactive input prompts. Fails if required variables are missing. |
-refresh-only |
terraform apply -refresh-only |
Refreshes the state file to match real-world resources without applying configuration changes. |
-destroy |
terraform apply -destroy |
Creates and applies a plan to destroy all managed resources. Equivalent to terraform destroy. |
-replace |
terraform apply -replace="resource" |
Forces replacement of a specific resource instance instead of an in-place update. |
-invoke |
terraform apply -invoke="action" |
Runs a specific provider action instead of the full apply lifecycle. |
-json |
terraform apply -json |
Outputs the apply results in JSON format. |
Input and Variable Management
Controlling how variables are passed to the apply operation is crucial for repeatability. The terraform apply -var="my_variable=test" option allows passing in a variable value directly on the command line. If my_variable is used to define an instance name, this command ensures the infrastructure is provisioned with "test" as the instance name. Similarly, terraform apply -var-file="varfile.tfvars" applies changes while using variable values from a specified .tfvars file. This is preferable to hardcoding values or relying on manual input in automated scripts.
The -input=false flag prevents Terraform from prompting for any input during the apply process. Instead of prompting, Terraform proceeds using existing values from .tfvars files, environment variables, or configuration defaults. If any required variable is missing, the command will fail. This is essential for CI/CD pipelines where interactive prompts are impossible and silent failures or unexpected defaults must be avoided.
Targeting and Partial Deployment
The -target flag allows engineers to apply changes only to targeted resources rather than all pending changes. For example, terraform apply -target=aws_instance.env0-instance will apply changes only to the resource named env0-instance of type aws_instance. While useful for troubleshooting or partial deployments, using -target is generally not recommended for regular production workflows. It can lead to dependencies being skipped, potentially causing inconsistencies in the infrastructure state. The Terraform state graph relies on dependencies to determine order; bypassing parts of this graph with -target can result in a state file that does not accurately reflect the actual infrastructure dependencies.
State Locking and Concurrency
Terraform uses state locking to prevent multiple users or processes from making changes to the same state file simultaneously. The terraform apply -lock=false option disables this feature. This is particularly useful in automated environments where locking might cause timeouts or where the locking mechanism is not applicable. However, it must be used with extreme caution. Disabling locking allows other engineers to run concurrent commands against the same workspace, which can result in state corruption or conflicting changes. It should only be used when the user is certain that no other operations are running against the same state.
The -parallelism=<n> option lets you specify the number of operations run in parallel. This is useful when limiting concurrent operations inside a cloud provider that has strict rate limits. Exceeding these limits can result in throttling errors. By setting a specific parallelism value, engineers can manage the load on the provider API.
Output Formatting
The terraform apply -compact-warnings option improves the readability of Terraform output by condensing warnings into a more concise format. While warnings are important, they can sometimes clutter the terminal output in verbose pipelines. This flag minimizes the visual noise while still preserving the information.
Advanced Flags: Replace, Destroy, and Invoke
Beyond standard configuration changes, Terraform provides flags for more aggressive or specific operational tasks.
Forced Resource Replacement
The terraform apply -replace=resource flag forces Terraform to replace a specific resource instance instead of updating it in-place. This is often required when a taint or forced recreation is necessary, such as when a critical attribute changes that cannot be updated without recreation. For example, terraform apply -replace=aws_instance.example will destroy and recreate the example instance. This flag should be used sparingly and usually only while troubleshooting, as forcing replacement can disrupt services and is not a standard part of the update lifecycle.
Destruction Workflows
The terraform apply -destroy flag creates and applies a plan whose goal is to destroy all remote objects managed by the configuration, leaving an empty state. This is equivalent to running terraform destroy. The -destroy flag was added to terraform apply in version 0.15.2; prior versions only supported it on terraform plan. Like a regular apply, it shows the plan and prompts for confirmation unless -auto-approve is also passed. This flag is useful when combining destroy planning with other planning options, such as -var, -var-file, or -target, in a single command. It also allows saving a destroy plan with terraform plan -destroy -out=tfplan for a two-step approval workflow, ensuring that the exact resources intended for destruction are reviewed before the final apply.
Provider Actions
The terraform apply -invoke='action.TYPE.LABEL' flag runs a specific provider action instead of applying the rest of the configuration. Actions are a feature introduced in Terraform 1.14+ (announced at HashiConf 2025). They allow providers to expose imperative operations outside the normal create/read/update/delete lifecycle. For example, a provider might expose an action to rotate credentials or trigger a backup that does not fit the standard CRUD model. This flag shifts terraform apply from a state-convergence tool to a tool for executing specific provider-defined tasks.
Refresh-Only and State Drift
State drift occurs when the actual infrastructure changes outside of Terraform’s management, causing the state file to become out of sync with reality. The terraform apply -refresh-only option instructs Terraform to refresh the state file to match the real-world resources without applying any configuration changes. When the actual infrastructure is suspected to be out of sync (e.g., due to manually deleted or externally altered resources), running this command updates the state file with the detected changes. This is a diagnostic and repair tool, allowing engineers to realign the state file with reality before proceeding with a standard apply.
Failure Handling and Best Practices
Running terraform apply without thinking is a common path to disaster. The mechanics are simple, but the edge cases are not. Best practices include always reviewing the plan before applying, especially in production. In automated environments, using Saved Plan Mode ensures that the plan applied is the one reviewed. For interactive work, allowing the prompt provides a safety check.
When an apply fails partway through, the state file may be partially updated. Terraform records the successful changes and leaves the failed ones unrecorded. The next terraform apply will attempt to complete the remaining changes. Engineers should never manually edit the state file to fix this unless absolutely necessary and with deep understanding of the state format. Instead, they should rely on Terraform’s ability to reconcile state. If a resource fails due to a provider error or rate limiting, using -parallelism to reduce concurrency or retrying the apply often resolves the issue.
The -input=false flag is critical for automation to ensure that the process does not hang waiting for input. Similarly, explicitly defining all variables via -var or -var-file ensures that the apply is deterministic and not reliant on environment variables that may differ between local and CI environments.
Conclusion
terraform apply is the pivotal command in the Terraform lifecycle, responsible for transforming code into infrastructure. Its power lies in its ability to converge state, but this power requires careful management of flags and execution modes. The distinction between Automatic Plan Mode and Saved Plan Mode is fundamental to separating human review from machine execution. Flags like -target and -replace offer precision for troubleshooting but carry risks of state inconsistency if used in routine workflows. Advanced features like -invoke and -destroy expand the command's utility beyond simple CRUD operations.
Success with terraform apply depends on understanding its interaction with state locking, parallelism, and input handling. Disabling locking with -lock=false or ignoring input prompts with -input=false without full understanding of the environment can lead to corrupted state or failed pipelines. By mastering these mechanics, engineers can ensure that infrastructure changes are predictable, safe, and auditable. The command is not merely a runner for plans; it is a gatekeeper for infrastructure integrity, requiring a balance between automation efficiency and operational safety.