Pulumi stacks can be automatically destroyed after a set time, but the mechanism isn’t a simple timeout; it’s a deliberate choice to manage ephemeral infrastructure lifecycles.

Let’s watch a Pulumi stack delete itself. Imagine we have a main.tf file like this:

resource "random_id" "example" {
  byte_length = 8
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0" # Example AMI, replace with a valid one for your region
  instance_type = "t2.micro"

  tags = {
    Name    = "ephemeral-instance-${random_id.example.hex}"
    Managed = "Pulumi TTL"
  }
}

output "instance_id" {
  value = aws_instance.example.id
}

And we deploy this with pulumi up. Once it’s up, we want it to disappear in, say, 10 minutes. We achieve this by adding a ttl resource to our Pulumi program, typically in a separate file or alongside the main resources. In Python, this might look like:

import pulumi
import pulumi_aws as aws
import pulumi_random as random

# Create a random ID to make the instance name unique
random_id = random.RandomId("example",
    byte_length=8)

# Create an EC2 instance
instance = aws.ec2.Instance("example",
    ami="ami-0c55b159cbfafe1f0", # Example AMI, replace with a valid one for your region
    instance_type="t2.micro",
    tags={
        "Name": f"ephemeral-instance-{random_id.hex}",
        "Managed": "Pulumi TTL",
    })

# Export the instance ID
pulumi.export("instance_id", instance.id)

# --- This is the TTL resource ---
# We want this instance to be destroyed 10 minutes (600 seconds) after deployment
ttl_resource = aws.cloudwatch.LogMetricFilter("ttl-metric-filter",
    log_group_name="/aws/codebuild/pulumi-ttl-example", # Replace with your actual log group
    pattern="Pulumi TTL",
    metric_name="PulumiTTLTrigger",
    metric_namespace="Pulumi",
    default_value=1,
    action_group_name="DestroyStack", # This is a custom action group name, not a Pulumi keyword
    action_group_arn="arn:aws:codepipeline:us-east-1:123456789012:pipeline/MyPulumiPipeline" # Replace with your actual ARN
)

# In a real-world scenario, you'd likely use a Pulumi Provider for TTL or a custom resource
# that triggers a Pulumi CLI command to destroy the stack.
# For demonstration, we'll simulate the intent.
# The actual mechanism often involves a scheduled event triggering a Pulumi destroy.

The ttl concept in Pulumi isn’t a built-in attribute on every resource. Instead, it’s implemented through external automation that monitors your deployed resources and triggers a pulumi destroy command after a specified duration. A common pattern involves:

  1. Tagging Resources: You tag your deployed resources with metadata indicating they are managed by a TTL policy and the expiry time (e.g., pulumi:ttl:expiry: 2023-10-27T10:00:00Z).
  2. Scheduled Job: A scheduled job (like an AWS Lambda function triggered by CloudWatch Events, a Kubernetes CronJob, or a GitHub Actions scheduled workflow) runs periodically.
  3. Inventory Check: This job queries your cloud provider for resources tagged with TTL metadata.
  4. Expiry Logic: It checks if the current time has passed the expiry time for any of these resources.
  5. Stack Destruction: If a TTL has expired, the job identifies the Pulumi stack associated with those resources and executes pulumi destroy --stack <stack-name> to tear down the entire stack.

The key is that Pulumi itself isn’t actively counting down. It’s the external automation that initiates the destruction command. This allows for flexible scheduling and integration with existing CI/CD pipelines.

A common misconception is that you can simply add a ttl: "10m" property to a Pulumi resource. While some providers might offer custom resources that abstract this away, the core mechanism relies on external orchestration. The aws.cloudwatch.LogMetricFilter example above is a simulation of a mechanism; a real implementation would likely involve a custom Pulumi component or a separate automation script.

The next step in managing ephemeral infrastructure is to implement a robust tagging strategy that includes not just expiry but also ownership and purpose, enabling more sophisticated lifecycle management policies.

Want structured learning?

Take the full Pulumi course →