Skip to main content

File Extension

ubx source files use the .iac extension.

Syntax

# This is a comment
// This is also a comment

block_keyword "type" "name" {
  attribute_key = value
  nested_object = {
    key = value
  }
  list_value = ["a", "b", "c"]
}

Value Types

TypeExampleNotes
String"eu-west-1"Double-quoted
Number42, 3.14Integer or float
Booleantrue, false
Object{ key = value }Nested key-value pairs
List["a", "b"]Ordered list
Pending ref~unit.x.y.zAsync cloud output
Resolved refinput.nameCompile-time variable
Interpolation"${input.env}-bucket"Embedded expressions

Attribute Naming

Attribute keys use snake_case in .iac files, automatically converted to camelCase in generated TypeScript:
instance_class = "db.t3.micro"   # .iac
# → instanceClass: "db.t3.micro"  # TypeScript

The ~ Sigil and Pending<T>

The ~ prefix marks values that resolve at apply time:
# Resolved<string> — known at compile time
engine = "postgres"

# Pending<string> — known only after apply
host = ~unit.aws_rds_instance.db.endpoint
Pending&lt;T&gt; propagates. If a value depends on a Pending&lt;T&gt;, it is also Pending&lt;T&gt;. The code generator converts Pending&lt;T&gt; references into Pulumi Output&lt;T&gt;.apply() chains automatically. See The Pending&lt;T&gt; Type System for a full deep dive.

Block Types

Resource Blocks — create cloud resources

BlockPurposeLabels
unitSingle cloud resource"type" "name"
componentReusable component"name"
deployHelm/Kustomize deployment"type" "name"
syncGitOps target (ArgoCD/Flux)"type" "name"

Value Blocks — define values

BlockPurposeLabels
inputStack variable"name"
outputStack output"name"
localReusable computed value"name"
dataRead-only cloud lookup"type" "name"

Modifier Blocks

BlockPurposeLabels
extendEnvironment-specific overridesvaries
importImport existing resource"type" "name"
movedRename resource in statenone
providerPin provider version"name"

Governance Blocks

BlockPurposeLabels
policyCompile-time compliance"name"
remoteCross-stack reference"name"
interfaceStack output contracts"name"
workspaceMulti-repo orchestration"name"

String Interpolation

input "env" { default = "staging" }

unit "aws_s3_bucket_v2" "logs" {
  bucket = "${input.env}-app-logs"    # → "staging-app-logs"
}
With Pending&lt;T&gt;:
unit "aws_s3_bucket_v2" "replica" {
  bucket = "${~unit.aws_s3_bucket_v2.primary.bucket}-replica"
  # → primary.bucket.apply(b => `${b}-replica`)
}

Meta-Arguments

These work on unit, component, deploy, and sync blocks:
ArgumentDescription
count = NCreate N copies; use count.index (0-based)
for_each = mapIterate over map; use each.key / each.value
when = conditionConditionally create the resource
depends_on = [...]Explicit dependency ordering
lifecycle { ... }prevent_destroy, ignore_changes, create_before_destroy
cost_limit = NMonthly cost ceiling in USD (requires AI)