CDK AWS: Infrastructure as TypeScript Code
Welcome to TopperBlog! 👋
I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.
🎯 What I Write About:
• AI/ML Engineering & LLMs
• Web3 & Blockchain Development
• System Design & Architecture
• Interview Preparation (FAANG)
• Freelancing & Remote Work
• Modern Tech Stacks (Next.js, React, Rust, TypeScript)
• Performance Optimization & Best Practices
💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.
📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.
🌐 Let's connect and grow together in this amazing tech journey!
#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering
AWS CDK Infrastructure as TypeScript Code
AWS CDK (Cloud Development Kit) is an infrastructure-as-code framework that lets you define AWS infrastructure using TypeScript, Python, Java, or other languages. Here's a comprehensive guide:
Core Concepts
CDK vs CloudFormation:
- CDK generates CloudFormation templates
- Write imperative code instead of declarative YAML/JSON
- Reusable constructs and higher-level abstractions
- Type safety with TypeScript
Basic Setup
npm install -g aws-cdk
cdk init app --language typescript
npm install
Simple Example: Web Application Stack
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as iam from 'aws-cdk-lib/aws-iam';
export class WebAppStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Create VPC
const vpc = new ec2.Vpc(this, 'WebVpc', {
maxAzs: 2,
cidrMask: 24,
});
// Create S3 bucket
const bucket = new s3.Bucket(this, 'WebBucket', {
versioned: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
// Create security group
const sg = new ec2.SecurityGroup(this, 'WebSG', {
vpc,
description: 'Security group for web servers',
allowAllOutbound: true,
});
sg.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
'Allow HTTP'
);
sg.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(443),
'Allow HTTPS'
);
// Create IAM role for EC2
const role = new iam.Role(this, 'WebServerRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
});
bucket.grantReadWrite(role);
// Create EC2 instance
const instance = new ec2.Instance(this, 'WebServer', {
vpc,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
machineImage: ec2.MachineImage.latestAmazonLinux2(),
role,
securityGroup: sg,
keyName: 'my-key-pair',
});
// User data script
instance.addUserData(
'yum update -y',
'yum install -y httpd',
'systemctl start httpd',
'systemctl enable httpd'
);
// Outputs
new cdk.CfnOutput(this, 'BucketName', {
value: bucket.bucketName,
description: 'S3 Bucket Name',
});
new cdk.CfnOutput(this, 'InstancePublicIP', {
value: instance.instancePublicIp,
description: 'EC2 Instance Public IP',
});
}
}
const app = new cdk.App();
new WebAppStack(app, 'WebAppStack');
Advanced Example: Microservices Architecture
import * as cdk from 'aws-cdk-lib';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as logs from 'aws-cdk-lib/aws-logs';
export class MicroservicesStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPC
const vpc = new ec2.Vpc(this, 'MicroservicesVpc', {
maxAzs: 2,
natGateways: 1,
});
// RDS Database
const database = new rds.DatabaseInstance(this, 'Database', {
engine: rds.DatabaseEngine.postgres({
version: rds.PostgresEngineVersion.VER_14,
}),
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
vpc,
multiAz: true,
allocatedStorage: 20,
storageType: rds.StorageType.GP2,
removalPolicy: cdk.RemovalPolicy.DESTROY,
deletionProtection: false,
});
// ECS Cluster
const cluster = new ecs.Cluster(this, 'EcsCluster', {
vpc,
});
// Add capacity
cluster.addCapacity('DefaultAutoScalingGroup', {
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.SMALL
),
desiredCapacity: 2,
});
// Task Definition
const taskDef = new ecs.Ec2TaskDefinition(this, 'TaskDef', {
networkMode: ecs.NetworkMode.BRIDGE,
});
const container = taskDef.addContainer('AppContainer', {
image: ecs.ContainerImage.fromRegistry('nginx:latest'),
memoryLimitMiB: 512,
logging: ecs.LogDriver.awsLogs({
streamPrefix: 'ecs',
logRetention: logs.RetentionDays.ONE_WEEK,
}),
});
container.addPortMappings({
containerPort: 80,
hostPort: 80,
protocol: ecs.Protocol.TCP,
});
// ECS Service
const service = new ecs.Ec2Service(this, 'Service', {
cluster,
taskDefinition: taskDef,
desiredCount: 2,
});
// Load Balancer
const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', {
vpc,
internetFacing: true,
});
const listener = lb.addListener('Listener', {
port: 80,
});
listener.addTargets('EcsTarget', {
port: 80,
targets: [service],
healthCheck: {
path: '/',
interval: cdk.Duration.seconds(60),
},
});
// Outputs
new cdk.CfnOutput(this, 'LoadBalancerDNS', {
value: lb.loadBalancerDnsName,
});
new cdk.CfnOutput(this, 'DatabaseEndpoint', {
value: database.dbInstanceEndpointAddress,
});
}
}
const app = new cdk.App();
new MicroservicesStack(app, 'MicroservicesStack');
Reusable Constructs
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
interface StaticSiteProps extends cdk.StackProps {
domainName: string;
}
export class StaticSite extends cdk.Stack {
public readonly bucket: s3.Bucket;
public readonly distribution: cloudfront.Distribution;
constructor(scope: cdk.App, id: string, props: StaticSiteProps) {
super(scope, id, props);
// S3 bucket for website
this.bucket = new s3.Bucket(this, 'WebsiteBucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
// CloudFront distribution
this.distribution = new cloudfront.Distribution(this, 'Distribution', {
defaultBehavior: {
origin: new origins.S3Origin(this.bucket),
viewerProtocolPolicy:
cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
defaultRootObject: 'index.html',
domainNames: [props.domainName],
});
new cdk.CfnOutput(this, 'DistributionDomain', {
value: this.distribution.domainName,
});
}
}
Common CDK Commands
# Synthesize to CloudFormation
cdk synth
# Deploy stack
cdk deploy
# Deploy specific stack
cdk deploy WebAppStack
# Destroy stack
cdk destroy
# List stacks
cdk list
# Diff changes
cdk diff
# Watch for changes
cdk watch
Best Practices
- Organize by layers: Separate networking, compute, database
- Use constructs: Build reusable components
- Environment configuration: Use context values
- Tagging: Apply consistent tags across resources
- Outputs: Export important values
- Testing: Use assertions to validate stacks
- Version control: Track infrastructure changes
Key Advantages
✅ Type safety with TypeScript
✅ Code reusability through constructs
✅ Easier testing and validation
✅ Programmatic infrastructure
✅ Reduced boilerplate vs CloudFormation
✅ Powerful abstractions for complex architectures
AWS CDK significantly improves infrastructure-as-code workflows by combining the power of programming languages with AWS infrastructure management.