Love Terraform but hate HCL? CDKTF lets you write Terraform configs in TypeScript, Python, Java, C#, or Go.
What is CDKTF?
CDK for Terraform (CDKTF) is an open-source project by HashiCorp that lets you define Terraform infrastructure using programming languages instead of HCL.
Quick Start
npm install -g cdktf-cli
cdktf init --template=typescript --providers=aws
Your First CDKTF Stack
import { Construct } from "constructs";
import { App, TerraformStack, TerraformOutput } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import { S3Bucket } from "@cdktf/provider-aws/lib/s3-bucket";
import { Instance } from "@cdktf/provider-aws/lib/instance";
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
new AwsProvider(this, "aws", { region: "us-east-1" });
// S3 Bucket
const bucket = new S3Bucket(this, "app-bucket", {
bucket: "my-app-assets-2026",
tags: { Environment: "production" },
});
// EC2 Instance
const server = new Instance(this, "web-server", {
ami: "ami-0c02fb55956c7d316",
instanceType: "t3.micro",
tags: { Name: "WebServer" },
});
new TerraformOutput(this, "bucket-name", { value: bucket.bucket });
new TerraformOutput(this, "server-ip", { value: server.publicIp });
}
}
const app = new App();
new MyStack(app, "my-infra");
app.synth();
cdktf deploy
Loops and Conditions (Why CDKTF Wins)
// Create 3 identical servers with a loop
const serverNames = ["web-1", "web-2", "web-3"];
serverNames.forEach(name => {
new Instance(this, name, {
ami: "ami-0c02fb55956c7d316",
instanceType: "t3.micro",
tags: { Name: name },
});
});
// Conditional resources
if (isProduction) {
new Instance(this, "monitoring", {
instanceType: "t3.large",
// ...
});
}
In HCL you would need count, for_each, and conditional expressions. In CDKTF — just use TypeScript.
Reusable Constructs
class WebApp extends Construct {
public readonly url: string;
constructor(scope: Construct, id: string, props: { domain: string; size: string }) {
super(scope, id);
const bucket = new S3Bucket(this, "assets", {
bucket: `${props.domain}-assets`,
});
const server = new Instance(this, "server", {
instanceType: props.size,
ami: "ami-0c02fb55956c7d316",
});
this.url = server.publicDns;
}
}
// Use it
const app1 = new WebApp(this, "app1", { domain: "example.com", size: "t3.micro" });
const app2 = new WebApp(this, "app2", { domain: "staging.example.com", size: "t3.small" });
CDKTF vs Pulumi vs HCL Terraform
| Feature | CDKTF | Pulumi | HCL Terraform |
|---|---|---|---|
| Languages | TS, Python, Go, Java, C# | TS, Python, Go, C# | HCL |
| State Backend | Terraform (S3, Cloud) | Pulumi Cloud, S3 | S3, Cloud |
| Provider Ecosystem | All Terraform providers | Most TF providers | All native |
| Existing TF Code | Import directly | Convert needed | Native |
| Testing | Jest/Vitest | Built-in | Terratest |
Key Advantage: Full Terraform Ecosystem
CDKTF generates standard Terraform JSON. This means every Terraform provider, every module, every backend — it all works. You get TypeScript DX with Terraform reliability.
Need managed infrastructure for data extraction? Check out my Apify actors — no infrastructure management needed. For custom solutions, email spinov001@gmail.com.
Top comments (0)