Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Terraform vs CDK and CDKTF

By Kokil Thapa | Last reviewed: September 2026

You need repeatable cloud infrastructure, but the tooling split is confusing. Terraform vs CDK and CDKTF is not three random acronyms — it is three different answers to the same problem: how you describe servers, networks, and services before they exist. Terraform uses its own declarative language. AWS CDK lets you write real TypeScript, Python, or Java. CDK for Terraform (CDKTF) sits in the middle and generates Terraform from familiar languages. If you already ship apps with infrastructure as code with Terraform, this comparison helps you decide whether CDK or CDKTF earns a place beside it.

What is the difference between Terraform, AWS CDK, and CDKTF?

All three are infrastructure-as-code (IaC) tools. They turn a definition file into cloud resources through a plan-and-apply cycle. The difference is the language you write in and the engine that executes the change.

Terraform (HashiCorp, now part of IBM's ecosystem) uses HashiCorp Configuration Language (HCL). You declare desired state. The Terraform CLI talks to provider plugins for AWS, Azure, GCP, Cloudflare, and hundreds of other targets. State is stored in a local file or a remote backend.

AWS CDK is Amazon's framework. You write constructs in TypeScript, Python, Java, C#, or Go. CDK synthesizes CloudFormation templates. CloudFormation creates and updates AWS resources. There is no Terraform state file. AWS owns the lifecycle through CloudFormation stacks.

CDKTF (CDK for Terraform) uses the AWS CDK programming model but outputs Terraform configuration. You get typed constructs in TypeScript or Python. The generated HCL runs through the normal Terraform workflow. Remote state, workspaces, and provider version pinning all behave like plain Terraform.

Three IaC Paths to CloudTerraformHCL source filesAWS CDKTypeScript / PythonCDKTFTS / Python to HCLTerraform CLIPlan + ApplyCloudFormationStack deployGenerated HCLThen TerraformMulti-cloudAWS, Azure, GCPAWS onlyNative constructsMulti-cloudReal languages
Terraform vs CDK and CDKTF: three source languages, two execution engines, one cloud outcome

Think of it as a fork in the road. Terraform and CDKTF share the Terraform execution engine. AWS CDK takes a separate path through CloudFormation. That single difference drives state handling, drift detection, and how much AWS-specific sugar you get.

How does each tool define and deploy infrastructure?

Each tool follows a similar mental model: write code, preview changes, apply them. The commands and artifacts differ.

Terraform workflow

You maintain .tf files, run terraform init, then plan and apply. Providers download on init. State tracks resource IDs.

# main.tf — minimal VPC on AWS
terraform {
  required_version = ">= 1.9.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.region
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = { Name = "app-vpc" }
}

Run terraform plan -out=tfplan to preview. Run terraform apply tfplan to commit. Store state remotely — S3 with DynamoDB locking is the common AWS pattern covered in Terraform remote state on S3 with locking.

AWS CDK workflow

You define a CDK app with stacks and constructs. CDK synthesizes CloudFormation JSON/YAML. Deployment goes through the AWS CDK CLI or CI pipeline.

// lib/network-stack.ts — AWS CDK (TypeScript)
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export class NetworkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    new ec2.Vpc(this, 'AppVpc', {
      maxAzs: 2,
      natGateways: 1,
    });
  }
}

Run cdk synth to generate templates. Run cdk deploy to push stacks. CloudFormation handles rollback on failure. See the AWS CDK Developer Guide for construct libraries and bootstrapping.

CDKTF workflow

CDKTF projects look like CDK apps but emit Terraform JSON/HCL into a cdktf.out directory. You still run standard Terraform commands on the output.

// main.ts — CDKTF (TypeScript)
import { Construct } from 'constructs';
import { App, TerraformStack } from 'cdktf';
import { AwsProvider } from '@cdktf/provider-aws';

class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);
    new AwsProvider(this, 'aws', { region: 'ap-south-1' });
    // Use generated provider bindings for resources
  }
}

const app = new App();
new MyStack(app, 'demo');
app.synth();

Run cdktf synth, then terraform -chdir=cdktf.out/stacks/demo init and apply. The HashiCorp CDKTF documentation covers provider generation with cdktf get.

IaC Deploy PipelineGit PushCI LintSynth / PlanPR ReviewApply / DeployTerraform / CDKTFterraform planterraform applyRemote state lockAWS CDKcdk synthcdk deployCFN stack eventsShared CI StepsPolicy scanCost estimateDrift check
CI/CD pipeline differences in Terraform vs CDK and CDKTF deployments

Which tool wins on state management, drift, and rollback?

State is where Terraform and CDKTF pull ahead of raw AWS CDK for teams that operate across clouds or self-hosted servers.

Terraform stores a state file mapping resource addresses to real cloud IDs. Remote backends with locking prevent concurrent apply collisions. Drift happens when someone changes resources outside IaC. Run terraform plan to surface it. Import existing resources with terraform import as described in bringing existing resources under Terraform control.

AWS CDK delegates state to CloudFormation. Each stack tracks its resources. Rollback is built in — a failed update reverts automatically. That is excellent for AWS-only shops. It is awkward when you also manage Cloudflare DNS, a VPS on Hetzner, and a managed MySQL instance outside AWS.

CDKTF inherits Terraform state semantics entirely. Generated code is an implementation detail. Your ops team still manages backends, workspaces, and state migration. If you already follow safe Terraform state management, CDKTF fits without retraining.

On production deployments I maintain, Terraform state in S3 with DynamoDB locking has been the least surprising choice when the same repo also provisions DNS and a Linux VPS alongside AWS resources.

How do Terraform, CDK, and CDKTF compare on language, testing, and ecosystem?

Language choice affects who can contribute, how you test, and how fast new hires become productive.

CriteriaTerraform (HCL)AWS CDKCDKTF
Primary languagesHCL (+ JSON optionally)TypeScript, Python, Java, C#, GoTypeScript, Python, Java, C#, Go
Cloud scopeMulti-cloud, 3000+ providersAWS primary; limited third-partyMulti-cloud via Terraform providers
Execution engineTerraform CLICloudFormationTerraform CLI
State modelTerraform state fileCloudFormation stack stateTerraform state file
High-level abstractionsModules (HCL)L2/L3 constructs, patternsConstructs + generated bindings
Unit testingterraform test, Terratest (Go)assertions, Jest/pytest snapshotsJest/pytest + Terraform plan in CI
Policy scanningCheckov, OPA, Sentinelcdk-nag, CloudFormation GuardCheckov on generated HCL
Community modulesTerraform Registry (massive)AWS Solutions ConstructsSmaller; reuse TF modules
License / governanceBSL 1.1 (OpenTofu fork exists)Apache 2.0 (AWS project)MPL 2.0 (HashiCorp)
Best fitPlatform / multi-cloud teamsAWS-native app teamsDev teams wanting TS + TF state

Language ergonomics

HCL is purpose-built for infrastructure. Loops, conditionals, and for_each cover most cases. Complex business logic gets awkward fast. That is why teams reach for Terragrunt or generate HCL from scripts.

AWS CDK shines when your app team already writes TypeScript. A VPC construct with sensible defaults takes ten lines. L3 patterns like ApplicationLoadBalancedFargateService wire load balancers, ECS, and IAM in one class. Read more in AWS CDK as infrastructure-as-real-code.

CDKTF gives you IDE autocomplete and type checking. Provider bindings are generated from Terraform provider schemas. The trade-off is an extra synth step and generated files in version control or CI artifacts.

Testing and quality gates

Run Checkov scans on Terraform in every pull request. CDK projects use cdk-nag for AWS best-practice rules. CDKTF projects should scan the synth output, not just the TypeScript source.

Policy-as-code matters for regulated workloads. Terraform's Sentinel and OPA integrations are mature. CDK relies more on pre-synth linting and CloudFormation Guard on synthesized templates.

Which IaC Tool?Start hereMulti-cloud?YesNoNeed real language?TypeScript / PythonCDKTFTyped + TF stateTerraformHCL + modulesAWS CDKApp team on AWS
Decision tree for Terraform vs CDK and CDKTF based on cloud scope and team skills

When should a small team or Nepal-based startup pick each option?

Budget and team size matter as much as technical fit. A Kathmandu SaaS team with two developers and a Rs 15,000/month (~USD 112) VPS does not need the same stack as a multi-account AWS enterprise.

Pick Terraform when

  • You manage mixed infrastructure: AWS for app servers, Cloudflare for DNS, and a bare-metal or VPS database.
  • Your ops person knows HCL already or you want the largest module ecosystem.
  • You need portable skills — Terraform job demand remains high globally and in remote roles.
  • You want straightforward integration with GitLab CI, GitHub Actions, or Atlantis as covered in Terraform CI/CD with GitHub Actions.

For VPS-first workloads, plain Terraform without CDKTF is often enough. A beginner-friendly path exists in Terraform for VPS provisioning.

Pick AWS CDK when

  • Everything lives in AWS — ECS Fargate, RDS, S3, Lambda, Cognito.
  • Your developers write TypeScript daily and hate learning HCL.
  • You want L3 constructs that encode AWS Well-Architected defaults.
  • CloudFormation rollback and stack-level lifecycle are acceptable trade-offs.

Pick CDKTF when

  • Developers insist on TypeScript or Python but platform engineers mandate Terraform state and providers.
  • You are migrating from CDK on AWS to a multi-cloud footprint and want to reuse programming patterns.
  • You need generated provider types without giving up the Terraform Registry module ecosystem.

CDKTF adds complexity. You maintain application code, generated HCL, provider bindings, and Terraform backends. Skip it if HCL modules already cover your needs via reusable Terraform modules.

Real-world overlap with app delivery

I regularly deploy Laravel applications with GitLab CI and Deployer on Ubuntu VPS instances. Terraform provisions the server, firewall rules, and DNS records. The app deploy pipeline stays separate. That split — IaC for infrastructure, Deployer for code — keeps concerns clean. Similar patterns appear on sister sites sharing a Deployer 7 pipeline, documented in our Notary Kathmandu portfolio case.

If you need full-stack delivery including server setup, see Linux system administration services and enterprise application development for teams that want app code and infrastructure handled together.

Laravel Prod Stack (Typical)TerraformVPS + DNS + SSLUbuntu VPSApache + PHP 8.4Deployer 7GitLab CI releaseAWS CDK path (alt)ECS Fargate + RDS + ALBCloudFormation stacksApp team owns infra codeHigher AWS bill, less opsTerraform path (typical)VPS + managed DBMulti-provider supportLower cost for SMBFamiliar to DevOps hire
Terraform vs CDK and CDKTF in practice: VPS Terraform stacks vs AWS CDK for containerised apps

What are the hidden costs and migration paths between them?

Switching IaC tools mid-project is expensive. Plan the choice against a three-year horizon.

Operational costs

Terraform itself is free to run locally. Terraform Cloud, Spacelift, and Env0 add per-resource or seat pricing. Compare options in Spacelift vs Terraform Cloud. AWS CDK is free; you pay for underlying AWS resources and CloudFormation operations.

CDKTF adds Node.js or Python runtime requirements in CI. Build times increase because cdktf get regenerates provider bindings when schemas change. Pin provider versions the same way you would in HCL — see Terraform provider version pinning.

Migration scenarios

  1. CloudFormation/CDK to Terraform: Use former2 or manual import. Expect weeks of parity testing. State import is tedious but well documented.
  2. Terraform to CDK: Rare. You lose multi-cloud unless you wrap non-AWS resources awkwardly.
  3. Terraform to CDKTF: Incremental. Rewrite one stack at a time. Keep the same remote backend. Run both HCL and CDKTF stacks in one repo during transition.
  4. CDK to CDKTF: Conceptual overlap in constructs helps. Execution engine swap is the hard part — CloudFormation semantics do not transfer directly.

License changes pushed some teams toward OpenTofu. If governance matters, read Terraform vs OpenTofu: what changed before committing new greenfield work.

CI/CD integration tips

Store Terraform plans as CI artifacts. Require human approval before apply on production. Use Terragrunt to keep Terraform DRY when you repeat the same VPC pattern across staging and production.

For CDK, run cdk diff in pull requests. Block merges when IAM policies broaden unexpectedly. Combine with Infracost for Terraform cost estimates on whichever path emits HCL.

Validate JSON policy files and module outputs with the JSON formatter tool before committing generated artifacts.

Common mistakes

  • Choosing AWS CDK for one Lambda function while the rest of the stack is Terraform — two state models, double training.
  • Committing CDKTF generated output without pinning provider versions — CI breaks on the next cdktf get.
  • Skipping remote state on Terraform because "we are just testing" — lost state means painful recreation.
  • Ignoring drift detection — schedule weekly terraform plan in CI as described in Terraform drift detection strategies.

Separate IaC from configuration management. Terraform and CDK provision resources. Ansible or cloud-init installs packages and hardens the OS. The distinction is covered in Terraform vs Ansible.

Key Takeaways

  • Terraform is the default for multi-cloud and mixed VPS plus cloud setups — largest module registry and ops tooling.
  • AWS CDK fits AWS-native teams who already write TypeScript and want L3 constructs with CloudFormation rollback.
  • CDKTF bridges developer language preference with Terraform state — use it only when that bridge is worth the synth overhead.
  • Never mix state models casually; pick one execution engine per environment boundary.
  • Scan, plan, and review in CI regardless of tool — Checkov for HCL, cdk-nag for CDK, both for CDKTF output.
  • For small Nepal teams on a budget, Terraform on VPS plus a separate app deploy pipeline often beats a full AWS CDK footprint.

People Also Ask

Can CDKTF replace Terraform completely?

No. CDKTF generates Terraform configuration — it does not replace the Terraform CLI, providers, or state backends. You still run terraform plan and terraform apply. CDKTF replaces HCL authorship, not the Terraform engine.

Is AWS CDK better than Terraform for AWS-only projects?

For teams fluent in TypeScript, AWS CDK is often faster to write and includes higher-level AWS patterns. Terraform remains stronger for cross-service consistency, third-party providers, and teams with existing HCL modules. Many AWS shops use both — CDK for app infra, Terraform for DNS and SaaS integrations.

Does CDKTF support all Terraform providers?

CDKTF can generate bindings for any Terraform provider via cdktf provider add. Coverage depends on provider schema quality. Popular providers like AWS, Google, and Azure are well supported. Niche providers may need manual HCL for edge resources.

Which tool is easier to learn for PHP or Laravel developers?

HCL is simpler than TypeScript if you only touch infrastructure occasionally. AWS CDK or CDKTF in TypeScript feels familiar if you already use JavaScript build tools with Vite 8.x on the frontend. For Laravel teams deploying to VPS, start with plain Terraform HCL — less moving parts, direct path from Terraform workspaces and environments to production.

Pick the right IaC tool and ship infrastructure you can maintain

Terraform vs CDK and CDKTF is not a purity contest. Terraform wins breadth and operational maturity. AWS CDK wins AWS developer ergonomics. CDKTF is the compromise when languages collide with platform standards. Match the tool to your cloud scope, team skills, and state requirements — then lock in CI gates before the stack grows.

Need help designing a deploy pipeline for a Laravel app, VPS stack, or hybrid cloud setup? Contact us to talk through infrastructure choices, or explore custom software development for full-stack delivery from code to production.

Frequently Asked Questions

All three are infrastructure-as-code tools with a plan-and-apply cycle. Terraform uses HCL and the Terraform CLI with provider plugins. AWS CDK uses TypeScript, Python, Java, C#, or Go and synthesizes CloudFormation templates. CDKTF uses the CDK programming model but generates Terraform configuration that runs through the normal Terraform workflow.

CDK for Terraform generates Terraform HCL or JSON from typed constructs in TypeScript, Python, or other CDK-supported languages.

No. CDKTF generates Terraform configuration; you still need the Terraform CLI, providers, remote backends, and state management.

Pick Terraform when you manage mixed infrastructure across AWS, Cloudflare, VPS hosts, or bare metal and want the largest module registry on the Terraform Registry. It fits platform teams who need portable skills, mature ops tooling like Atlantis and GitLab CI, and straightforward remote state with S3 plus DynamoDB locking. On production deployments I maintain, Terraform state has been the least surprising choice when the same repo provisions DNS and a Linux VPS alongside AWS resources.

Choose AWS CDK when everything lives in AWS — ECS Fargate, RDS, S3, Lambda, Cognito — and your developers already write TypeScript daily. L3 constructs like ApplicationLoadBalancedFargateService wire load balancers, ECS, and IAM in one class with AWS Well-Architected defaults. CloudFormation handles deployment with built-in rollback on failure. The trade-off is stack-level state tied to AWS, which gets awkward when you also manage Cloudflare DNS or a VPS outside AWS.

Use CDKTF when developers insist on TypeScript or Python but platform engineers mandate Terraform state, providers, and the Terraform Registry module ecosystem. It helps teams migrating from CDK toward multi-cloud who want to reuse construct patterns without abandoning remote backends and workspaces. Skip it if HCL modules already cover your needs — you will maintain application code, generated HCL, provider bindings, and Terraform backends, plus an extra synth step in CI.

Terraform stores a state file mapping resource addresses to real cloud IDs, with remote backends and locking to prevent concurrent apply collisions. AWS CDK delegates state to CloudFormation stacks — rollback is built in, but cross-cloud resources are awkward. CDKTF inherits Terraform state semantics entirely; generated code is an implementation detail. Drift detection runs through terraform plan for Terraform and CDKTF. For AWS CDK, each CloudFormation stack tracks its own resources independently.

Terraform and CDKTF share the Terraform CLI execution engine — providers talk to AWS, Azure, GCP, Cloudflare, and hundreds of other targets. AWS CDK takes a separate path: it synthesizes CloudFormation JSON or YAML, and CloudFormation creates and updates AWS resources. That single fork drives state handling, drift detection, and how much AWS-specific abstraction you get. Never mix state models casually; pick one execution engine per environment boundary.

Terraform: maintain .tf files, run terraform init, terraform plan -out=tfplan, then terraform apply tfplan with remote state on S3. AWS CDK: define stacks and constructs, run cdk synth to generate templates, then cdk deploy — CloudFormation handles the update. CDKTF: write constructs in TypeScript or Python, run cdktf synth to emit HCL into cdktf.out, then run standard terraform init and apply inside that output directory. Each path previews changes before committing them.

AWS CDK is AWS-primary with limited third-party support. It synthesizes CloudFormation, which only manages AWS resources natively. If your stack includes Cloudflare DNS, a Hetzner VPS, and a managed MySQL instance outside AWS, Terraform or CDKTF fits better because they use Terraform providers covering 3000+ targets. Choosing AWS CDK for one Lambda while the rest of the stack is Terraform creates two state models and double training — a common mistake worth avoiding.

Terraform uses terraform test and Terratest in Go, with Checkov, OPA, and Sentinel for policy scanning. AWS CDK uses Jest or pytest assertions plus cdk-nag for AWS best-practice rules, and CloudFormation Guard on synthesized templates. CDKTF projects should scan the synth output with Checkov, not just the TypeScript source — run Jest or pytest plus Terraform plan in CI. Regardless of tool, scan, plan, and review in every pull request before production apply.

Switching mid-project is expensive — plan against a three-year horizon. Terraform is free locally; Terraform Cloud, Spacelift, and Env0 add per-resource or seat pricing. AWS CDK is free but you pay for AWS resources and CloudFormation operations. CDKTF adds Node.js or Python runtime requirements in CI and longer build times when cdktf get regenerates provider bindings. CloudFormation-to-Terraform migration via former2 or manual import expects weeks of parity testing. Terraform-to-CDKTF is incremental — rewrite one stack at a time while keeping the same remote backend.

Budget and team size matter. A Kathmandu SaaS team with two developers and a Rs 15,000/month (~USD 112) VPS does not need the same stack as a multi-account AWS enterprise. For VPS-first workloads, plain Terraform provisioning the server, firewall rules, and DNS — with a separate Deployer pipeline for Laravel app code — often beats a full AWS CDK footprint. Pick AWS CDK only when everything genuinely lives in AWS and your developers already write TypeScript and want L3 constructs with CloudFormation rollback.

Store Terraform plans as CI artifacts and require human approval before production apply. Use Terragrunt to keep Terraform DRY across staging and production VPC patterns. Integrate with GitLab CI, GitHub Actions, or Atlantis. For CDK, run cdk diff in pull requests and block merges when IAM policies broaden unexpectedly. CDKTF pipelines need cdktf synth before terraform plan on generated output. Combine with Infracost for cost estimates on whichever path emits HCL. Pin provider versions the same way you would in plain HCL to avoid CI breaks.

Mixing AWS CDK for one Lambda while the rest runs on Terraform creates two state models and double training. Committing CDKTF generated output without pinning provider versions breaks CI on the next cdktf get. Skipping remote state because you are just testing leads to lost state and painful resource recreation. Ignoring drift detection — schedule weekly terraform plan in CI. Also, do not confuse IaC with configuration management: Terraform and CDK provision resources; Ansible or cloud-init installs packages and hardens the OS afterward.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: