
September 10, 2026
13 min read
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.
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.
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.
| Criteria | Terraform (HCL) | AWS CDK | CDKTF |
|---|---|---|---|
| Primary languages | HCL (+ JSON optionally) | TypeScript, Python, Java, C#, Go | TypeScript, Python, Java, C#, Go |
| Cloud scope | Multi-cloud, 3000+ providers | AWS primary; limited third-party | Multi-cloud via Terraform providers |
| Execution engine | Terraform CLI | CloudFormation | Terraform CLI |
| State model | Terraform state file | CloudFormation stack state | Terraform state file |
| High-level abstractions | Modules (HCL) | L2/L3 constructs, patterns | Constructs + generated bindings |
| Unit testing | terraform test, Terratest (Go) | assertions, Jest/pytest snapshots | Jest/pytest + Terraform plan in CI |
| Policy scanning | Checkov, OPA, Sentinel | cdk-nag, CloudFormation Guard | Checkov on generated HCL |
| Community modules | Terraform Registry (massive) | AWS Solutions Constructs | Smaller; reuse TF modules |
| License / governance | BSL 1.1 (OpenTofu fork exists) | Apache 2.0 (AWS project) | MPL 2.0 (HashiCorp) |
| Best fit | Platform / multi-cloud teams | AWS-native app teams | Dev 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.
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.
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
- CloudFormation/CDK to Terraform: Use former2 or manual import. Expect weeks of parity testing. State import is tedious but well documented.
- Terraform to CDK: Rare. You lose multi-cloud unless you wrap non-AWS resources awkwardly.
- 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.
- 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 planin 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
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.

