Terraform is a declarative tool: you describe the desired end state of your infrastructure, and Terraform figures out how to reach it. Most of the time, this model works extremely well. Resources are created, updated, or destroyed based on configuration changes, and Terraform tracks those changes through state.
However, not all infrastructure-related tasks fit neatly into a resource lifecycle. Common examples include:
Traditionally, these activities were performed using provisioners. While provisioners made such tasks possible, they also introduced ambiguity around lifecycle, ordering, error handling, and idempotency. Over time, their limitations became clear, and Terraform began discouraging their use except as a last resort.
Terraform actions address this problem directly. Actions provide an explicit mechanism for executing imperative operations within a Terraform workflow. Unlike resources, actions are not managed over time, do not represent persistent infrastructure objects, and are not reconciled against state. Instead, they invoke a specific operation at a specific point in the deployment process.
Actions are:
terraform applyThis makes them particularly useful for tasks that must happen alongside infrastructure changes, such as post-deployment configuration steps, administrative operations, or one-off API calls.
By introducing actions, Terraform offers a cleaner, safer, and more expressive alternative to provisioners, while preserving the declarative approach that makes Terraform reliable and predictable.
In the sections that follow, we'll explore how actions are defined, how they are executed, and how different providers support them.
Terraform actions are defined using an action block, which declares an imperative
operation that Terraform should execute when the action is invoked. Unlike resources or data sources,
an action does not represent a managed object. Instead, it represents an explicit operation that is
intentionally run at a specific point in the configuration's deployment process.
At a high level, an action block answers three questions:
An action block follows a provider-defined structure, but the general format is
consistent:
The config block may contain arguments, nested blocks, or a combination of both.
Its structure is entirely provider-specific and defines how the action behaves when it is
executed.
Similarly to other resources, action blocks also support the count and
for_each meta-arguments, allowing multiple action instances to be declared by a single
configuration block when needed.
Elsewhere in the configuration, an action can be referenced using the
action.<TYPE>.<LABEL> syntax. This allows actions to participate in
dependency relationships with other resources.
Because actions are implemented by providers, they benefit from the same provider-level capabilities as other Terraform constructs, including:
The action block also has several important properties that clearly distinguish
it from other Terraform blocks:
action block alone does not cause it to execute.
Actions must be explicitly invoked, either through the CLI or via supported action-triggering
mechanisms.In the following section, we'll look more closely at how actions are invoked, when they run during a Terraform workflow, and how execution success or failure affects an apply.
Defining an action block alone does not cause it to execute. Terraform actions are
explicitly invoked, either directly through the Terraform CLI or indirectly as part of the standard
terraform apply workflow. This design reinforces Terraform's declarative model by
ensuring that imperative steps run only when intentionally triggered and under well-defined
conditions.
Terraform currently supports two invocation models:
terraform applyEach model serves different use cases and provides varying levels of control over when and how actions are executed.
Actions can be executed explicitly using the Terraform CLI, independent of a full
terraform apply run. This is useful for operational tasks, ad-hoc workflows,
and situations where rerunning an action is needed without modifying infrastructure.
Let's use this code example defining a local_command action to illustrate CLI
invocation:
A typical invocation follows this pattern:
terraform apply -invoke=action.<TYPE>.<LABEL>
This command executes the specified action without planning or applying infrastructure changes. For example:
Direct invocation allows operators to:
action_trigger
In many cases, actions must run automatically as part of infrastructure changes. Terraform
supports this pattern through action triggers, which define conditions under which an action
should execute during terraform apply.
Conceptually, triggers define when an action should run, while the action block defines what should run.
Action triggers reside in the lifecycle block.
The action_trigger block specifies a set of arguments that determine which events
trigger one or more provider actions, under which conditions the action runs, and which actions
Terraform invokes:
The action_trigger rule is a block that supports the following arguments:
events - a list of lifecycle events to invoke the action;
may include one or more of the following events: before_create,
after_create, before_update, after_updatecondition - an optional expression that evaluate to true
to invoke the actionactions - an ordered list of actions to run when the events
and condition arguments are met.
More than one action_trigger rule can be included in a lifecycle block.
During the apply phase, Terraform evaluates all action_trigger blocks and invokes
the actions whose trigger conditions are satisfied. If an action fails, Terraform treats the
failure as an apply failure and halts further execution.
Importantly, because actions do not represent managed state, they are not replayed automatically unless their trigger conditions are met again or they are explicitly invoked.
action_trigger Example:
The action triggers enable workflows such as:
Terraform actions are provider-defined, which means both their availability and behavior depend entirely on the provider implementing them. Unlike core Terraform constructs such as resources or data sources, actions are not universally supported or standardized across providers. As a result, understanding provider-specific capabilities is essential when designing action-based workflows.
The sections below provide a high-level overview of action support across commonly used providers. The exact action types, inputs, and behavior may vary by provider version and should always be verified against provider documentation.
The Local provider from Hashicorp is used to execute commands and manage local resources, such as files. It supports:
local_command action which invokes an executable on the local machine.The AWS provider exposes actions for operational and administrative tasks that interact directly with AWS APIs but are not modeled as persistent resources.
Here's a list of the actions currently supported by the AWS Terraform provider:
aws_cloudfront_create_invalidation
- Invalidates objects in CloudFront distribution cache. This action creates an invalidation
request and waits for it to complete. Useful for ensuring fresh content is served after updates.
aws_codebuild_start_build
- Starts a new build in AWS CodeBuild. This action will initiate a build and wait for it to
complete, providing progress updates during execution. Commonly used to trigger CI/CD pipelines
or custom build workflows.
aws_ec2_stop_instance
- Stops an EC2 instance. This action will gracefully stop the instance and wait for it to reach
the stopped state. Useful for operational automation, maintenance windows, or cost optimization.
aws_events_put_events
- Sends custom events to Amazon EventBridge so that they can be matched to rules. This action
provides an imperative way to emit events from Terraform plans (e.g., deployment notifications)
while still allowing Terraform to manage when the emission occurs through action_trigger
lifecycle events.
aws_lambda_invoke
- Invokes an AWS Lambda function with a specified payload. This action allows for imperative
invocation of Lambda functions with full control over invocation parameters. Often used for
operational hooks or serverless automation.
aws_ses_send_email
- Sends an email using Amazon SES. This action allows for imperative email sending with full
control over recipients, content, and formatting. Useful for notifications or alerts triggered
by Terraform workflows.
aws_sfn_start_execution
- Starts an execution of a Step Functions state machine, enabling orchestration of complex workflows.
aws_sns_publish
- Publishes a message to an Amazon SNS topic for notifications, fan-out messaging, or event-driven
integrations.
Azure support for actions is currently limited, and the only available action type listed in the Terraform Registry is for virtual machine power management:
azurerm_virtual_machine_power
- Controls the power state of a virtual machine in Azure. You can power off, power on, or restart
a VM as part of an action, enabling operational steps such as cost optimization or maintenance
workflows.
Terraform actions provide an explicit way to execute imperative operations alongside declarative infrastructure management. They address long-standing gaps that were previously filled by provisioners, while preserving Terraform's core principles of clarity, predictability, and dependency-aware execution.
Throughout this article, we explored how actions:
terraform applyKey points to keep in mind:
Used correctly, Terraform actions help bridge the gap between declarative infrastructure and real-world operational needs, without sacrificing readability, safety, or control.
More Terraform Tutorials
Getting Started with Terraform
Understanding Terraform Variable Precedence
Terraform Value Types Tutorial
Terraform count Explained with Practical Examples
Terraform for_each Tutorial with Practical Examples
Exploring Terraform dynamic Blocks with GCP Examples
Working with External Data in Terraform
Terraform Modules FAQ