CDK for Terraform (CDKTF) lets you define multi-cloud infrastructure using TypeScript, Python, Java, C#, or Go — with full IDE support, type checking, and access to every Terraform provider.
Why CDKTF Matters
Terraform's HCL is powerful but limited: no loops over complex data, no real functions, no package management. CDKTF gives you a real programming language while keeping Terraform's state management and provider ecosystem.
What you get for free:
- Write infrastructure in TypeScript/Python/Java/C#/Go
- Access ALL 3,000+ Terraform providers (AWS, GCP, Azure, Cloudflare, etc.)
- IDE auto-complete and type checking for every resource
- Use npm/pip packages for complex logic
- Generates Terraform JSON — full compatibility with existing workflows
- Unit test your infrastructure with Jest/pytest
Quick Start
# Install
npm install -g cdktf-cli
# Create project
mkdir infra && cd infra
cdktf init --template=typescript --providers=aws
# Add providers
cdktf provider add aws
cdktf provider add cloudflare
# Deploy
cdktf deploy
# Diff
cdktf diff
Multi-Cloud Setup
import { Construct } from "constructs";
import { App, TerraformStack, TerraformOutput } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import { Instance } from "@cdktf/provider-aws/lib/instance";
import { S3Bucket } from "@cdktf/provider-aws/lib/s3-bucket";
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, "data-bucket", {
bucket: "my-app-data-2024",
tags: { Environment: "production", ManagedBy: "cdktf" },
});
// EC2 instance
const server = new Instance(this, "web-server", {
ami: "ami-0c55b159cbfafe1f0",
instanceType: "t3.micro",
tags: { Name: "web-server" },
});
new TerraformOutput(this, "bucket-arn", { value: bucket.arn });
new TerraformOutput(this, "server-ip", { value: server.publicIp });
}
}
const app = new App();
new MyStack(app, "my-infrastructure");
app.synth();
Reusable Components
class WebService extends Construct {
public readonly url: string;
constructor(scope: Construct, id: string, props: {
name: string;
port: number;
replicas: number;
environment: Record<string, string>;
}) {
super(scope, id);
const sg = new SecurityGroup(this, "sg", {
ingress: [{
fromPort: props.port,
toPort: props.port,
protocol: "tcp",
cidrBlocks: ["0.0.0.0/0"],
}],
});
const lb = new Lb(this, "lb", {
loadBalancerType: "application",
securityGroups: [sg.id],
});
this.url = lb.dnsName;
}
}
// Usage across stacks
new WebService(this, "api", { name: "api", port: 8080, replicas: 3, environment: { NODE_ENV: "prod" } });
new WebService(this, "web", { name: "web", port: 3000, replicas: 2, environment: { API_URL: "..." } });
Unit Testing Infrastructure
import { Testing } from "cdktf";
import { MyStack } from "./main";
describe("MyStack", () => {
it("creates an S3 bucket with correct tags", () => {
const app = Testing.app();
const stack = new MyStack(app, "test");
const synth = Testing.synth(stack);
expect(synth).toHaveResource("aws_s3_bucket");
expect(synth).toHaveResourceWithProperties("aws_s3_bucket", {
tags: { Environment: "production" },
});
});
it("creates exactly 1 EC2 instance", () => {
const app = Testing.app();
const stack = new MyStack(app, "test");
const synth = Testing.synth(stack);
expect(Testing.toHaveResourceCount(synth, "aws_instance", 1)).toBeTruthy();
});
});
CDKTF vs HCL Comparison
| Feature | HCL | CDKTF |
|---|---|---|
| Type checking | Limited | Full |
| IDE support | Basic | Excellent |
| Loops | for_each |
Native for/map |
| Functions | Built-in only | Any npm package |
| Testing | terraform test |
Jest/pytest |
| Package mgmt | Registry | npm/pip/maven |
Useful Links
- GitHub
- Documentation
- Construct Hub — reusable constructs
Building cloud infrastructure automation? Check out my developer tools on Apify for ready-made web scrapers, or email spinov001@gmail.com for custom solutions.
Top comments (0)