Two Different Philosophies
AWS CDK (Cloud Development Kit) and Terraform represent two fundamentally different approaches to Infrastructure as Code. Terraform takes a declarative approach: you describe the desired final state in HCL, and Terraform calculates the plan to get there. AWS CDK takes an imperative approach: you write TypeScript or Python code that generates CloudFormation templates, with the full power of a real programming language.
In 2026, both tools have reached remarkable maturity and often coexist in the same organisations. Choosing between them depends on your context: cloud strategy, team skills, and infrastructure complexity.
Key CDK Concepts
CDK is organised around three hierarchical concepts:
- App: the entry point of your CDK programme, contains one or more stacks
- Stack: CloudFormation deployment unit, corresponds to a CF template
- Construct: reusable building block representing one or more AWS resources
Constructs exist at three levels:
- L1 (CfnXxx): direct wrapper of CloudFormation resources, 1:1 with CF
- L2: high-level abstractions with sensible defaults (opinionated)
- L3 (Patterns): ready-to-use complete architectures (e.g. ApplicationLoadBalancedFargateService)
Side-by-Side Comparison: ECS Fargate Service
Here is the same ECS Fargate service defined in CDK TypeScript and Terraform HCL:
CDK TypeScript
import { Stack, StackProps } from 'aws-cdk-lib';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
import { Construct } from 'constructs';
export class PaymentServiceStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const cluster = new ecs.Cluster(this, 'Cluster', {
clusterName: 'payment-cluster',
containerInsights: true,
});
const service = new ecs_patterns.ApplicationLoadBalancedFargateService(
this, 'PaymentService', {
cluster,
cpu: 512,
memoryLimitMiB: 1024,
desiredCount: 2,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('nginx:latest'),
containerPort: 8080,
environment: { NODE_ENV: 'production' },
},
publicLoadBalancer: true,
}
);
// Auto-scaling in 3 lines
const scaling = service.service.autoScaleTaskCount({ maxCapacity: 10 });
scaling.scaleOnCpuUtilization('CpuScaling', { targetUtilizationPercent: 70 });
}
}
Terraform HCL
resource "aws_ecs_cluster" "main" {
name = "payment-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
}
resource "aws_ecs_task_definition" "payment" {
family = "payment-service"
cpu = "512"
memory = "1024"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
execution_role_arn = aws_iam_role.ecs_exec.arn
container_definitions = jsonencode([{
name = "app"
image = "nginx:latest"
portMappings = [{ containerPort = 8080 }]
environment = [{ name = "NODE_ENV", value = "production" }]
}])
}
resource "aws_ecs_service" "payment" {
name = "payment-service"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.payment.arn
desired_count = 2
launch_type = "FARGATE"
network_configuration {
subnets = var.private_subnets
security_groups = [aws_security_group.app.id]
}
load_balancer {
target_group_arn = aws_lb_target_group.payment.arn
container_name = "app"
container_port = 8080
}
}
# ... 50+ additional lines for ALB, SG, IAM, Auto Scaling
CDK drastically reduces code volume for AWS thanks to L3 constructs, but Terraform gives granular control over every parameter.
CDK Aspects: Automated Compliance
CDK Aspects allow you to apply compliance rules across all resources in a stack. This is a feature with no direct equivalent in Terraform:
class SecurityAspect implements cdk.IAspect {
visit(node: IConstruct): void {
if (node instanceof s3.Bucket) {
if (!node.encryptionKey) {
cdk.Annotations.of(node).addError(
'All S3 buckets must use customer-managed KMS keys'
);
}
}
if (node instanceof rds.DatabaseInstance) {
if (!node.storageEncrypted) {
cdk.Annotations.of(node).addError('RDS must have encryption enabled');
}
}
}
}
// Apply the aspect to the entire app
cdk.Aspects.of(app).add(new SecurityAspect());
CDK Testing with Jest
CDK allows you to test infrastructure like application code, with assertions on generated templates:
import { Template } from 'aws-cdk-lib/assertions';
test('ECS service has correct CPU allocation', () => {
const app = new cdk.App();
const stack = new PaymentServiceStack(app, 'TestStack');
const template = Template.fromStack(stack);
template.hasResourceProperties('AWS::ECS::TaskDefinition', {
Cpu: '512',
Memory: '1024',
RequiresCompatibilities: ['FARGATE'],
});
});
test('S3 buckets have versioning enabled', () => {
template.allResourcesProperties('AWS::S3::Bucket', {
VersioningConfiguration: { Status: 'Enabled' },
});
});
Terraform Advantages
- Native multi-cloud: same workflow for AWS, GCP, Azure, OVH, Kubernetes
- Massive community: 3000+ providers, Terraform Registry modules
- OpenTofu: open-source fork without commercial dependency
- Stability: HCL is less susceptible to breaking changes than an SDK
- Dev/ops separation: ops can contribute without mastering TypeScript
CDK Advantages
- Type safety: the TypeScript compiler catches errors before deployment
- IDE autocomplete: discover APIs without consulting documentation
- Reusability: constructs are npm packages shareable between teams
- Testing: native unit tests for infrastructure
- Powerful abstractions: L3 patterns radically reduce code volume
Decision Matrix
| Context | Recommendation |
|---|---|
| 100 % AWS team with strong TypeScript/Python culture | CDK |
| Multi-cloud (AWS + GCP, or AWS + OVH) | Terraform / OpenTofu |
| Mixed dev + ops team without programming culture | Terraform |
| AWS-only startup scaling fast | CDK (maximum productivity) |
| Complex infrastructure shared across multiple teams | Terraform (modules) or CDK (npm constructs) |
| Compliance and security policies to apply everywhere | CDK Aspects or Sentinel (Terraform) |
Conclusion
In 2026, CDK and Terraform are no longer really in competition — they address different needs. If your organisation is AWS-centric and your developers already write TypeScript, CDK offers unmatched productivity. If you manage multiple clouds, want simple governance, or your ops teams lack a programming culture, Terraform (or OpenTofu) remains the wisest choice. Many organisations use both: CDK for AWS application services, Terraform for the network foundation and multi-cloud layer.
