AWS CDK lets you define cloud infrastructure in familiar programming languages - Python, TypeScript, Java - and synthesise it into CloudFormation. Compared to writing raw CloudFormation or Terraform HCL, CDK gives you loops, conditionals, type safety, and reusable constructs.
This series covers practical CDK patterns using Python, with a consistent use case across all parts so the trade-offs are easy to compare.
Why CDK over CloudFormation for AWS-native workloads?
- CloudFormation is YAML or JSON - no loops, no conditionals, no abstraction. Any shared pattern gets copy-pasted.
- CDK uses a real programming language - loops, functions, classes, and type checks all apply to infrastructure the same way they apply to application code.
- L2 constructs handle boilerplate.
bucket.grant_read(fn)generates the IAM policy, role attachment, and resource reference in one call. The CloudFormation equivalent is four resources wired together manually. - The compiler catches mistakes before CloudFormation ever sees the template.
- CDK still synthesises to CloudFormation under the hood - rollbacks, drift detection, and stack history are unchanged.
Why CDK over Terraform for AWS-native workloads?
- Terraform’s strength is multi-cloud. For AWS-only workloads, that comes with overhead that doesn’t pay off - a state backend, a provider version to pin, and HCL alongside the application code.
- CDK uses CloudFormation as the deployment engine - AWS manages state natively. No S3 bucket for state, no DynamoDB table for locking, no
terraform initin the pipeline. - New AWS services appear in CDK constructs faster.
- IAM is easier. Terraform requires writing policy JSON by hand and threading ARNs between resources. CDK’s
grant_*methods generate least-privilege policies from the resource graph. - Terraform is the right call when infrastructure spans multiple cloud providers, or when the team already has a mature Terraform codebase.
Use case
Simple infrastructure by design - the CDK patterns are the point, not the resources.
The series
Chapter 1 - Project setup and bootstrapping
Getting a CDK project off the ground - directory structure, virtual environments, bootstrapping an AWS account, and understanding the synth/deploy cycle.
Chapter 2 - Managing configuration and context
How environment-specific values flow into CDK stacks - four approaches covering local static config, local dynamic config, SSM Parameter Store, and Secrets Manager, with trade-offs and code examples for each.
Chapter 3 - Writing and sharing constructs
Building L3 constructs - extracting resources into reusable units, the keyword-only props pattern, and sharing constructs across stacks.
Chapter 4 - Testing CDK stacks
Unit testing constructs and stacks with aws_cdk.assertions - fine-grained assertions, snapshot testing, and when each applies.
Chapter 5 - CI/CD with CDK
Automating CDK deployments with GitHub Actions, Jenkins, and Azure DevOps - auth setup, multi-environment promotion, and approval gates.
Notes
- All examples use Python and CDK v2.
- Steps are tested on WSL2/Ubuntu on Windows and native macOS terminal.
- More chapters added as I work through these patterns.