DEV Community

Alex Spinov
Alex Spinov

Posted on

Terraform CDK Has a Free API: Write Infrastructure as Code in TypeScript Instead of HCL

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
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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: "..." } });
Enter fullscreen mode Exit fullscreen mode

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();
  });
});
Enter fullscreen mode Exit fullscreen mode

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


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)