The lifecycle Meta-Argument
Hands-on: Try the Lifecycle Management tutorial.
The Resource Behavior page describes the general lifecycle for resources. Some details of
that behavior can be customized using the special nested lifecycle
block
within a resource block body:
resource "azurerm_resource_group" "example" { # ... lifecycle { create_before_destroy = true }}
Syntax and Arguments
lifecycle
is a nested block that can appear within a resource block.
The lifecycle
block and its contents are meta-arguments, available
for all resource
blocks regardless of type.
The arguments available within a lifecycle
block are create_before_destroy
,
prevent_destroy
, ignore_changes
, and replace_triggered_by
.
create_before_destroy
(bool) - By default, when Terraform must change a resource argument that cannot be updated in-place due to remote API limitations, Terraform will instead destroy the existing object and then create a new replacement object with the new configured arguments.The
create_before_destroy
meta-argument changes this behavior so that the new replacement object is created first, and the prior object is destroyed after the replacement is created.This is an opt-in behavior because many remote object types have unique name requirements or other constraints that must be accommodated for both a new and an old object to exist concurrently. Some resource types offer special options to append a random suffix onto each object name to avoid collisions, for example. Terraform CLI cannot automatically activate such features, so you must understand the constraints for each resource type before using
create_before_destroy
with it.Note that Terraform propagates and applies
create_before_destroy
meta-attribute behaviour to all resource dependencies. For example, if resource A with enabledcreate_before_destroy
depends on resource B with disabledcreate_before_destroy
(by default), then Terraform enablescreate_before_destroy
for resource B implicitly and stores it to the state file. You cannot overridecreate_before_destroy
tofalse
on resource B, because that would imply dependency cycles in the graph.Destroy provisioners of this resource do not run if
create_before_destroy
is set totrue
. This GitHub issue contains more details.prevent_destroy
(bool) - This meta-argument, when set totrue
, will cause Terraform to reject with an error any plan that would destroy the infrastructure object associated with the resource, as long as the argument remains present in the configuration.This can be used as a measure of safety against the accidental replacement of objects that may be costly to reproduce, such as database instances. However, it will make certain configuration changes impossible to apply, and will prevent the use of the
terraform destroy
command once such objects are created, and so this option should be used sparingly.Since this argument must be present in configuration for the protection to apply, note that this setting does not prevent the remote object from being destroyed if the
resource
block were removed from configuration entirely: in that case, theprevent_destroy
setting is removed along with it, and so Terraform will allow the destroy operation to succeed.ignore_changes
(list of attribute names) - By default, Terraform detects any difference in the current settings of a real infrastructure object and plans to update the remote object to match configuration.The
ignore_changes
feature is intended to be used when a resource is created with references to data that may change in the future, but should not affect said resource after its creation. In some rare cases, settings of a remote object are modified by processes outside of Terraform, which Terraform would then attempt to "fix" on the next run. In order to make Terraform share management responsibilities of a single object with a separate process, theignore_changes
meta-argument specifies resource attributes that Terraform should ignore when planning updates to the associated remote object.The arguments corresponding to the given attribute names are considered when planning a create operation, but are ignored when planning an update. The arguments are the relative address of the attributes in the resource. Map and list elements can be referenced using index notation, like
tags["Name"]
andlist[0]
respectively.resource "aws_instance" "example" { # ... lifecycle { ignore_changes = [ # Ignore changes to tags, e.g. because a management agent # updates these based on some ruleset managed elsewhere. tags, ] }}
Instead of a list, the special keyword
all
may be used to instruct Terraform to ignore all attributes, which means that Terraform can create and destroy the remote object but will never propose updates to it.Only attributes defined by the resource type can be ignored.
ignore_changes
cannot be applied to itself or to any other meta-arguments.replace_triggered_by
(list of resource or attribute references) - Added in Terraform 1.2. Replaces the resource when any of the referenced items change. Supply a list of expressions referencing managed resources, instances, or instance attributes. When used in a resource that usescount
orfor_each
, you can usecount.index
oreach.key
in the expression to reference specific instances of other resources that are configured with the same count or collection.References trigger replacement in the following conditions:
- If the reference is to a resource with multiple instances, a plan to update or replace any instance will trigger replacement.
- If the reference is to a single resource instance, a plan to update or replace that instance will trigger replacement.
- If the reference is to a single attribute of a resource instance, any change to the attribute value will trigger replacement.
You can only reference managed resources in
replace_triggered_by
expressions. This lets you modify these expressions without forcing replacement.resource "aws_appautoscaling_target" "ecs_target" { # ... lifecycle { replace_triggered_by = [ # Replace `aws_appautoscaling_target` each time this instance of # the `aws_ecs_service` is replaced. aws_ecs_service.svc.id ] }}
replace_triggered_by
allows only resource addresses because the decision is based on the planned actions for all of the given resources. Plain values such as local values or input variables do not have planned actions of their own, but you can treat them with a resource-like lifecycle by using them with theterraform_data
resource type.
Custom Condition Checks
You can add precondition
and postcondition
blocks with a lifecycle
block to specify assumptions and guarantees about how resources and data sources operate. The following examples creates a precondition that checks whether the AMI is properly configured.
resource "aws_instance" "example" { instance_type = "t2.micro" ami = "ami-abc123" lifecycle { # The AMI ID must refer to an AMI that contains an operating system # for the `x86_64` architecture. precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } }}
Custom conditions can help capture assumptions, helping future maintainers understand the configuration design and intent. They also return useful information about errors earlier and in context, helping consumers more easily diagnose issues in their configurations.
Refer to Custom Conditions for more details.
Literal Values Only
The lifecycle
settings all affect how Terraform constructs and traverses
the dependency graph. As a result, only literal values can be used because
the processing happens too early for arbitrary expression evaluation.