If you already know Python, learning an entirely new configuration language just to manage cloud infrastructure feels like a detour. That is exactly the problem CDK for Terraform, usually shortened to CDKTF, was built to solve. It lets you define real cloud infrastructure, servers, storage buckets, databases, networking, using regular Python code instead of Terraform’s native HashiCorp Configuration Language (HCL).
This guide walks through what CDKTF is, how to set it up, and how to provision a simple AWS infrastructure using nothing but Python.
What is CDK for Terraform?
Terraform is one of the most widely used infrastructure-as-code (IaC) tools. You describe the cloud resources you want, and Terraform figures out how to create, update, or remove them to match that description. Normally, that description is written in HCL, a domain-specific configuration language.
CDKTF changes that. Instead of writing HCL, you write Python (or TypeScript, Java, C#, or Go) using CDKTF’s libraries. When you run your code, CDKTF synthesizes it into a standard Terraform configuration behind the scenes. That means everything you already know about Python, loops, functions, classes, conditionals, works when defining infrastructure, and the result is still fully compatible with the wider Terraform ecosystem, including its providers, state backends, and remote execution tools.
Prerequisites
Before starting, make sure you have the following installed:
- Python 3.8 or later
- Node.js 16 or later (CDKTF’s CLI runs on Node.js even though your infrastructure code is Python)
- Terraform CLI
- An AWS account with credentials configured locally (any provider works, this guide uses AWS for the example)
Install the CDKTF CLI using npm:
npm install --global cdktf-cli@latest
Verify it installed correctly:
Setting up a new CDKTF Python project
Create a new project directory and initialize a Python CDKTF project inside it:
mkdir cdktf-python-demo && cd cdktf-python-demo
cdktf init --template=python --local
The –local flag tells CDKTF to store Terraform’s state file locally rather than in a remote backend, which is fine for learning and testing. Once the command finishes, install the Python dependencies it generated:
pip install -r requirements.txt
You will also need the AWS provider bindings:
cdktf provider add "aws@~>5.0"
Writing infrastructure in Python
Open main.py in the generated project. CDKTF creates a starter file for you, but here is a minimal, complete example that provisions a single S3 bucket:
from constructs import Construct
from cdktf import App, TerraformStack
from cdktf_cdktf_provider_aws.provider import AwsProvider
from cdktf_cdktf_provider_aws.s3_bucket import S3Bucket
class MyStack(TerraformStack):
def __init__(self, scope: Construct, id: str):
super().__init__(scope, id)
AwsProvider(self, "AWS", region="us-east-1")
S3Bucket(
self,
"demo-bucket",
bucket="cdktf-python-demo-bucket-example",
tags={"ManagedBy": "CDKTF", "Language": "Python"},
)
app = App()
MyStack(app, "cdktf-python-demo")
app.synth()
That is a complete, working definition of infrastructure. There is no HCL anywhere in it. It is a Python class that inherits from TerraformStack, and inside its constructor it declares an AWS provider and a single S3 bucket resource, using ordinary Python keyword arguments to configure it.
Deploying the infrastructure
Before deploying, CDKTF needs to compile the Python code into a Terraform-readable format:
This generates a cdktf.out directory containing standard Terraform JSON configuration. You can inspect it if you are curious what CDKTF produced under the hood, but you will not need to edit it directly.
To see what CDKTF would change, run a plan:
And to actually create the bucket:
CDKTF will prompt for confirmation, then hand the synthesized configuration to Terraform, which provisions the resource exactly as it would if you had written the HCL by hand. Destroying the resource when you are done experimenting works the same way any Terraform project does:
Why this matters beyond a single script
The example above works well for one developer experimenting locally. Production use looks different. Once more than one person is touching the same infrastructure, a few problems show up quickly: state files need to live somewhere shared and locked so two people cannot apply conflicting changes at once, changes need a review step before they reach production, and someone needs a way to confirm that what is actually running still matches what the code says should be running.
Because CDKTF compiles down to standard Terraform configuration, it can run through the same tooling any other Terraform project uses to solve those problems. Teams that outgrow local state and one-off cdktf deploy commands typically run their synthesized configuration through a platform like Spacelift, which manages the plan and apply workflow, enforces review before changes reach production, and continuously checks for drift between the deployed infrastructure and the approved configuration. It treats a CDKTF Python stack the same way it treats any other Terraform-compatible infrastructure definition, which means the Python code from this guide can scale from a local experiment to something a full team manages without a rewrite. Spacelift’s Terraform at scale covers the governed workflow in more detail.
A lighter-weight alternative: python-terraform
If defining infrastructure directly in Python feels like more than you need right now, the python-terraform package takes a different approach: it is a thin Python wrapper around the Terraform CLI itself, letting you call init, plan, and apply from a Python script while your actual infrastructure stays written in ordinary HCL files. It is a reasonable option if you already have Terraform configuration and just want to trigger and parse it from Python, for example inside a test suite or a CI script, rather than rewriting your infrastructure definitions from scratch.
Wrapping up
CDKTF is a practical bridge for Python developers who need to manage cloud infrastructure without learning a second configuration language from scratch. The official CDKTF documentation covers additional constructs, other supported cloud providers, and more advanced patterns like reusable stacks, and is worth bookmarking once you move past a first working example like the one in this guide.

