AWS CDK Cheat Sheet
Overview
AWS Cloud Development Kit (CDK) is an open-source software development framework that allows you to define cloud infrastructure using familiar programming languages. Instead of writing declarative JSON or YAML templates, you use TypeScript, Python, Java, C#, or Go to create reusable infrastructure components called constructs. CDK synthesizes your code into AWS CloudFormation templates, giving you the full power of a programming language—loops, conditionals, abstractions—while maintaining the safety and repeatability of infrastructure as code.
CDK operates on three levels of constructs: L1 (CloudFormation resources mapped 1:1), L2 (higher-level abstractions with sensible defaults and helper methods), and L3 (patterns that combine multiple resources into common architectures). The Construct Library provides hundreds of pre-built L2 and L3 constructs covering most AWS services. CDK also includes the CDK Pipelines module for self-mutating CI/CD pipelines and integrates with tools like cdk-nag for policy validation and compliance checking.
Installation
Install CDK CLI
# Install globally via npm
npm install -g aws-cdk
# Verify installation
cdk --version
# Install specific version
npm install -g aws-cdk@2.150.0
Initialize a New Project
# TypeScript project
cdk init app --language typescript
# Python project
cdk init app --language python
source .venv/bin/activate
pip install -r requirements.txt
# Go project
cdk init app --language go
Bootstrap Your AWS Account
# Bootstrap default account/region
cdk bootstrap
# Bootstrap specific account and region
cdk bootstrap aws://123456789012/us-east-1
# Bootstrap with custom qualifier
cdk bootstrap --qualifier myapp --toolkit-stack-name CDKToolkit-myapp
# Bootstrap multiple regions
cdk bootstrap aws://123456789012/us-east-1 aws://123456789012/eu-west-1
# Bootstrap with execution policies
cdk bootstrap --cloudformation-execution-policies "arn:aws:iam::policy/AdministratorAccess"
Core Commands
| Command | Description |
|---|---|
cdk init | Create a new CDK project from template |
cdk synth | Synthesize CloudFormation template |
cdk deploy | Deploy stack to AWS |
cdk destroy | Delete deployed stack |
cdk diff | Compare deployed stack with local changes |
cdk ls | List all stacks in the app |
cdk bootstrap | Prepare AWS account for CDK deployments |
cdk watch | Watch for file changes and auto-deploy |
cdk doctor | Diagnose CDK environment issues |
cdk context | Manage cached context values |
Synthesize and Deploy
# Synthesize all stacks
cdk synth
# Synthesize specific stack
cdk synth MyStack
# Deploy all stacks
cdk deploy --all
# Deploy specific stack with auto-approve
cdk deploy MyStack --require-approval never
# Deploy with parameters
cdk deploy --parameters MyStack:BucketName=my-bucket
# Deploy with context values
cdk deploy -c environment=production
# Hot-swap deploy for faster iteration (dev only)
cdk deploy --hotswap
# Watch mode for continuous deployment
cdk watch
Diff and Inspection
# Show differences between deployed and local
cdk diff
# Diff specific stack
cdk diff MyStack
# Show synthesized template
cdk synth MyStack --json
# List stacks
cdk ls
# Show context values
cdk context
cdk context --reset
Stack Definition (TypeScript)
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
export class MyServiceStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// DynamoDB table
const table = new dynamodb.Table(this, 'ItemsTable', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// Lambda function
const fn = new lambda.Function(this, 'Handler', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'index.handler',
environment: {
TABLE_NAME: table.tableName,
},
});
// Grant Lambda read/write to DynamoDB
table.grantReadWriteData(fn);
// API Gateway
const api = new apigateway.RestApi(this, 'Api', {
restApiName: 'My Service',
});
api.root.addResource('items').addMethod('GET', new apigateway.LambdaIntegration(fn));
// Outputs
new cdk.CfnOutput(this, 'ApiUrl', { value: api.url });
}
}
Stack Definition (Python)
from aws_cdk import (
Stack, RemovalPolicy, CfnOutput,
aws_s3 as s3,
aws_lambda as _lambda,
aws_dynamodb as dynamodb,
)
from constructs import Construct
class MyServiceStack(Stack):
def __init__(self, scope: Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
bucket = s3.Bucket(self, "DataBucket",
versioned=True,
removal_policy=RemovalPolicy.DESTROY,
auto_delete_objects=True,
)
fn = _lambda.Function(self, "Processor",
runtime=_lambda.Runtime.PYTHON_3_12,
code=_lambda.Code.from_asset("lambda"),
handler="handler.main",
environment={"BUCKET": bucket.bucket_name},
)
bucket.grant_read_write(fn)
CfnOutput(self, "BucketName", value=bucket.bucket_name)
Configuration
cdk.json
{
"app": "npx ts-node --prefer-ts-exts bin/my-app.ts",
"watch": {
"include": ["**"],
"exclude": [
"README.md", "cdk*.json", "**/*.d.ts", "**/*.js",
"tsconfig.json", "package*.json", "yarn.lock", "node_modules", "test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:stackRelativeExports": true,
"environment": "development"
}
}
Environment-Specific Stacks
const app = new cdk.App();
const env = app.node.tryGetContext('environment') || 'dev';
new MyServiceStack(app, `MyService-${env}`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});
Advanced Usage
Custom Constructs
export class SecureBucket extends Construct {
public readonly bucket: s3.Bucket;
constructor(scope: Construct, id: string) {
super(scope, id);
this.bucket = new s3.Bucket(this, 'Bucket', {
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
enforceSSL: true,
versioned: true,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
}
}
CDK Pipelines
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';
const pipeline = new CodePipeline(this, 'Pipeline', {
pipelineName: 'MyPipeline',
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('owner/repo', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth'],
}),
});
pipeline.addStage(new MyAppStage(this, 'Prod', {
env: { account: '123456789012', region: 'us-east-1' },
}));
Aspects for Policy Enforcement
import * as cdk from 'aws-cdk-lib';
import { IConstruct } from 'constructs';
class BucketEncryptionChecker implements cdk.IAspect {
visit(node: IConstruct): void {
if (node instanceof s3.CfnBucket) {
if (!node.bucketEncryption) {
cdk.Annotations.of(node).addError('Bucket must have encryption enabled');
}
}
}
}
cdk.Aspects.of(app).add(new BucketEncryptionChecker());
Testing
import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { MyServiceStack } from '../lib/my-service-stack';
test('DynamoDB Table Created', () => {
const app = new cdk.App();
const stack = new MyServiceStack(app, 'TestStack');
const template = Template.fromStack(stack);
template.hasResourceProperties('AWS::DynamoDB::Table', {
BillingMode: 'PAY_PER_REQUEST',
});
template.resourceCountIs('AWS::Lambda::Function', 1);
});
Troubleshooting
| Issue | Solution |
|---|---|
cdk bootstrap fails with access denied | Ensure IAM user has cloudformation:* and s3:* permissions |
--hotswap not updating Lambda | Hot-swap only works for code changes, not config changes |
| Context value not found | Run cdk context --reset and re-synth |
Stack stuck in ROLLBACK_COMPLETE | Delete the stack manually in CloudFormation console, then redeploy |
Cannot find module 'constructs' | Run npm install — constructs is a peer dependency in CDK v2 |
| Circular dependency between stacks | Use CfnOutput and Fn.importValue or restructure into a single stack |
| Synth produces empty template | Ensure stacks are instantiated in bin/ entry point |