TTL Policy
A TTL (Time-To-Live) policy automatically destroys a stack and its resources after a specified duration. This is useful for ephemeral environments like development workspaces, testing infrastructure, or temporary demos that should be cleaned up automatically.
How It Works
When you attach a TTL policy to a stack, formae:
- Records when the stack was created or when the policy was attached
- Schedules destruction for when the TTL expires
- Automatically destroys the stack and all its resources when the time comes
The TTL countdown starts when the stack is first created with the policy attached. If you re-apply the stack, the TTL is not reset—the original creation time is preserved.
Configuration
A TTL policy has two settings:
| Property | Type | Description |
|---|---|---|
ttl |
Duration | How long the stack should live (e.g., 1.h, 24.h, 7.d) |
onDependents |
String | What to do if other resources depend on this stack: "abort" (default) or "cascade" |
The onDependents Setting
When a TTL expires, formae checks if any resources outside the stack depend on resources inside it. The onDependents setting controls what happens:
abort(default): Cancel the destruction if external resources depend on this stack. The stack remains intact until dependencies are removed.cascade: Delete dependent resources in other stacks as well, following the dependency chain.
Warning: Use
cascadewith caution. It can delete resources in other stacks if they depend on resources in the expiring stack.
Examples
Inline TTL Policy
Define a TTL policy directly in the stack:
amends "@formae/forma.pkl"
import "@formae/formae.pkl"
import "@aws/aws.pkl"
import "@aws/logs/loggroup.pkl"
local devTarget = new formae.Target {
label = "dev-target"
config = new aws.Config {
region = "us-east-1"
}
}
forma {
devTarget
new formae.Stack {
label = "feature-xyz"
description = "Temporary dev environment for feature XYZ"
policies = new Listing {
new formae.TTLPolicy {
ttl = 8.h // Destroy after 8 hours
onDependents = "abort" // Don't destroy if other resources depend on it
}
}
}
new loggroup.LogGroup {
label = "feature-logs"
stack = "feature-xyz"
target = devTarget.res
logGroupName = "/dev/feature-xyz/logs"
retentionInDays = 1
}
}
Reusable TTL Policy
Define a policy once and share it across multiple stacks:
amends "@formae/forma.pkl"
import "@formae/formae.pkl"
import "@aws/aws.pkl"
import "@aws/logs/loggroup.pkl"
// Reusable policy for all ephemeral dev environments
local ephemeralPolicy = new formae.TTLPolicy {
label = "ephemeral-4h"
ttl = 4.h
onDependents = "cascade"
}
local devTarget = new formae.Target {
label = "dev-target"
config = new aws.Config {
region = "us-east-1"
}
}
forma {
// Add the reusable policy to the forma
ephemeralPolicy
devTarget
// Stack for developer Alice
new formae.Stack {
label = "alice-dev"
description = "Alice's development environment"
policies = new Listing { ephemeralPolicy.res }
}
new loggroup.LogGroup {
label = "alice-logs"
stack = "alice-dev"
target = devTarget.res
logGroupName = "/dev/alice/logs"
}
// Stack for developer Bob
new formae.Stack {
label = "bob-dev"
description = "Bob's development environment"
policies = new Listing { ephemeralPolicy.res }
}
new loggroup.LogGroup {
label = "bob-logs"
stack = "bob-dev"
target = devTarget.res
logGroupName = "/dev/bob/logs"
}
}
Multiple Duration Tiers
Use different TTL policies for different environment types:
amends "@formae/forma.pkl"
import "@formae/formae.pkl"
// Short-lived for quick tests
local quickTest = new formae.TTLPolicy {
label = "quick-test-1h"
ttl = 1.h
onDependents = "cascade"
}
// Standard dev environment
local devEnv = new formae.TTLPolicy {
label = "dev-env-8h"
ttl = 8.h
onDependents = "abort"
}
// Longer-lived staging
local staging = new formae.TTLPolicy {
label = "staging-7d"
ttl = 7.d
onDependents = "abort"
}
forma {
quickTest
devEnv
staging
// Use the appropriate policy for each stack type
new formae.Stack {
label = "integration-test"
policies = new Listing { quickTest.res }
}
new formae.Stack {
label = "feature-dev"
policies = new Listing { devEnv.res }
}
new formae.Stack {
label = "release-staging"
policies = new Listing { staging.res }
}
}
Use Cases
Development environments: Create temporary workspaces that clean up automatically at the end of the workday.
CI/CD test infrastructure: Spin up infrastructure for integration tests that disappears when tests complete.
Demo environments: Provision infrastructure for customer demos that auto-destroys after the demo window.
Cost control: Prevent forgotten development resources from running indefinitely and accumulating costs.
Monitoring TTL
Check which stacks have TTL policies and when they expire:
formae inventory stacks
The output shows attached policies for each stack.