# Infrastructure as Code with AWS CDK
Today I learned how to use AWS Cloud Development Kit (CDK) to define cloud infrastructure using TypeScript, which provides significant advantages over traditional CloudFormation templates.
## The Evolution of IaC
Infrastructure as Code has evolved from manual scripts to declarative templates (CloudFormation, Terraform) and now to programming language constructs with AWS CDK. This evolution brings several benefits:
## Key Advantages of CDK
- **Type Safety**: Compile-time checks catch errors before deployment
- **Abstraction**: High-level constructs simplify complex infrastructure patterns
- **Reusability**: Create custom constructs for organization-specific patterns
- **Familiar Tools**: Use IDEs, testing frameworks, and version control as with application code
- **Logic & Loops**: Leverage programming language features for dynamic infrastructure
## Practical Implementation
I migrated our microservices infrastructure from CloudFormation to CDK, creating:
1. A base stack with shared VPC and security groups
2. Reusable constructs for standard microservice patterns
3. Environment-specific configurations using context variables
4. Custom aspects for enforcing security and compliance policies
## Results
The migration reduced our infrastructure code by approximately 60% while making it more maintainable and less error-prone. New service deployments that previously took days to configure now take hours, significantly accelerating our delivery pipeline.
Code Example
import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; export class MicroserviceStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // Create VPC and Fargate Cluster const vpc = new ec2.Vpc(this, 'ServiceVPC', { maxAzs: 2 }); const cluster = new ecs.Cluster(this, 'Cluster', { vpc }); // Define the Fargate Service const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef'); taskDefinition.addContainer('AppContainer', { image: ecs.ContainerImage.fromRegistry('my-app:latest'), memoryLimitMiB: 512, cpu: 256, portMappings: [{ containerPort: 80 }] }); // Create the service const service = new ecs.FargateService(this, 'Service', { cluster, taskDefinition, desiredCount: 2 }); // Set up load balancing const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc, internetFacing: true }); const listener = lb.addListener('Listener', { port: 80 }); listener.addTargets('Target', { port: 80, targets: [service] }); // Output the load balancer URL new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: lb.loadBalancerDnsName }); } }
AWSCDKIaCTypeScript