Python Terraform CDK — Core Concepts
What Terraform CDK is
Terraform CDK (CDKTF) is a framework that lets you define cloud infrastructure using programming languages — Python, TypeScript, Java, C#, or Go — instead of HashiCorp Configuration Language (HCL). Your Python code synthesizes into standard Terraform JSON, which Terraform’s core engine then plans and applies.
This means you get Python’s full power (loops, conditionals, functions, classes, packages) while leveraging Terraform’s mature state management and provider ecosystem (supporting AWS, GCP, Azure, and thousands of other services).
Key concepts
App and Stacks
Every CDKTF project starts with an App containing one or more Stack objects. A stack maps to a Terraform state file — an isolated unit of infrastructure:
from cdktf import App, TerraformStack
class WebStack(TerraformStack):
def __init__(self, scope, id):
super().__init__(scope, id)
# Define resources here
app = App()
WebStack(app, "production-web")
app.synth()
app.synth() generates Terraform JSON files in cdktf.out/. You can have multiple stacks — one for networking, one for compute, one for databases — each with independent state.
Providers
Providers connect CDKTF to cloud platforms. You add them to your stack:
from cdktf_cdktf_provider_aws.provider import AwsProvider
from cdktf_cdktf_provider_aws.instance import Instance
class WebStack(TerraformStack):
def __init__(self, scope, id):
super().__init__(scope, id)
AwsProvider(self, "aws", region="us-east-1")
Instance(self, "web-server",
ami="ami-0abcdef1234567890",
instance_type="t3.micro",
tags={"Name": "web-server-1"},
)
Provider packages are generated from Terraform provider schemas. They include full type hints, so your IDE provides autocomplete and type checking.
Resources and data sources
Resources represent infrastructure to create. Data sources look up existing infrastructure:
from cdktf_cdktf_provider_aws.data_aws_ami import DataAwsAmi
from cdktf_cdktf_provider_aws.instance import Instance
# Look up the latest Ubuntu AMI
ubuntu = DataAwsAmi(self, "ubuntu",
most_recent=True,
filter=[{
"name": "name",
"values": ["ubuntu/images/hvm-ssd/ubuntu-*-22.04-amd64-server-*"],
}],
owners=["099720109477"],
)
# Use it in a resource
Instance(self, "server",
ami=ubuntu.id,
instance_type="t3.micro",
)
The synthesis workflow
- Write Python code defining your infrastructure
- Synth —
cdktf synthruns your Python, producing Terraform JSON - Plan —
cdktf planshows what will be created, changed, or destroyed - Apply —
cdktf deployexecutes the plan
This is the same plan-apply workflow Terraform users know, but the input is Python instead of HCL.
Why use Python over HCL?
Loops for repeated resources
regions = ["us-east-1", "eu-west-1", "ap-southeast-1"]
for region in regions:
AwsProvider(self, f"aws-{region}", region=region, alias=region)
S3Bucket(self, f"logs-{region}",
provider=self.providers[region],
bucket=f"app-logs-{region}",
)
In HCL, you would use count or for_each, which are limited compared to real loops.
Reusable functions
def create_tagged_bucket(stack, name, environment):
return S3Bucket(stack, name,
bucket=f"{environment}-{name}",
tags={"Environment": environment, "ManagedBy": "cdktf"},
)
create_tagged_bucket(self, "data", "production")
create_tagged_bucket(self, "logs", "production")
create_tagged_bucket(self, "backups", "production")
Conditional logic
if environment == "production":
instance_type = "m5.xlarge"
multi_az = True
else:
instance_type = "t3.micro"
multi_az = False
How it compares
| Feature | CDKTF (Python) | Terraform HCL | AWS CDK | Pulumi |
|---|---|---|---|---|
| Language | Python, TS, Go, etc. | HCL | Python, TS, Go, etc. | Python, TS, Go, etc. |
| State management | Terraform | Terraform | CloudFormation | Pulumi service |
| Multi-cloud | Yes (all TF providers) | Yes | AWS only | Yes |
| Learning curve | Low (if you know Python) | Medium (new DSL) | Medium | Low |
| Maturity | Growing | Very mature | Mature (AWS) | Mature |
CDKTF’s unique advantage is combining Python’s expressiveness with Terraform’s provider ecosystem and battle-tested state management.
Common misconception
People sometimes think CDKTF replaces Terraform. It does not. CDKTF is a layer on top of Terraform. It generates Terraform JSON, uses Terraform’s state management, and relies on Terraform’s providers. If Terraform supports a cloud resource, CDKTF supports it. You can even mix CDKTF stacks with existing HCL configurations in the same project.
The one thing to remember: CDKTF lets you write infrastructure as real Python code — with loops, functions, and type checking — while Terraform handles the actual provisioning and state management underneath.
See Also
- Python Ansible Python Learn Ansible Python with a clear mental model so your Python code is easier to trust and maintain.
- Python Aws Boto3 Learn AWS Boto3 with a clear mental model so your Python code is easier to trust and maintain.
- Python Aws Dynamodb Python Learn AWS Dynamodb Python with a clear mental model so your Python code is easier to trust and maintain.
- Python Aws Lambda Python Learn AWS Lambda Python with a clear mental model so your Python code is easier to trust and maintain.
- Python Aws Lambda Use AWS Lambda with Python to remove setup chaos so Python projects stay predictable for every teammate.