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

  1. Write Python code defining your infrastructure
  2. Synthcdktf synth runs your Python, producing Terraform JSON
  3. Plancdktf plan shows what will be created, changed, or destroyed
  4. Applycdktf deploy executes 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

FeatureCDKTF (Python)Terraform HCLAWS CDKPulumi
LanguagePython, TS, Go, etc.HCLPython, TS, Go, etc.Python, TS, Go, etc.
State managementTerraformTerraformCloudFormationPulumi service
Multi-cloudYes (all TF providers)YesAWS onlyYes
Learning curveLow (if you know Python)Medium (new DSL)MediumLow
MaturityGrowingVery matureMature (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.

pythonterraforminfrastructuredevopsiac

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.