CDK is a compiler. Review the output.
AWS CDK lets you define infrastructure in a real programming language: loops, functions, types, packages. Then it synthesizes a CloudFormation template, and CloudFormation is what actually changes your account.
That makes CDK a compiler. And like any compiler, the interesting bugs live in the gap between the source you reviewed and the output that runs.
Small source changes, large output changes
Some CDK changes look harmless in a pull request and do a lot in the template:
- Changing a construct’s ID or moving it to a different place in the construct tree changes its logical ID. CloudFormation then sees a resource to delete and a new one to create. For a database or a bucket, that’s a replacement, not a rename.
- Upgrading
aws-cdk-libcan change what high-level constructs produce: new default settings, extra IAM permissions, different resource properties. - Feature flags in
cdk.jsonchange synthesis behavior. Turning one on can alter many resources at once.
None of this is visible in the TypeScript diff. All of it is visible in the template diff.
Make the template diff part of review
- Run
cdk diffin CI for every pull request and post the result as a comment. Reviewers should read it the way they’d read a database migration. Watch for lines marked as replacements, and for IAM and security group changes. - Snapshot-test the synthesized template. Commit the synthesized output (or use the
aws-cdk-lib/assertionsmodule) so any change to the generated CloudFormation fails a test until someone accepts it on purpose. Library upgrades stop being a surprise. - Assert the dangerous things explicitly. Write tests that fail if a stateful resource loses its
RemovalPolicy.RETAIN, if a bucket becomes public, or if a security group opens to0.0.0.0/0.
Protect what can’t be recreated
For stateful resources, defense in depth:
- Set
removalPolicy: RemovalPolicy.RETAINon databases, buckets and key stores. - Enable termination protection on production stacks.
- Use stack policies to deny replacement or deletion of specific resources, even if a template asks for it.
- Pin logical IDs with
overrideLogicalIdwhen you must refactor code without moving the resource.
CloudFormation has also gained stack refactoring, which can move resources between stacks or rename logical IDs without replacing them. It’s the safe way to do the reorganizations that used to require a careful manual import.
When CDK is the wrong layer
CDK’s power is abstraction, and abstraction cuts both ways. A custom construct library that hides 40 resources behind one line is great for the platform team that understands it and opaque to everyone else. If a construct needs its own documentation for reviewers to understand its diff, it’s doing too much.
The rule that keeps CDK safe is simple: review what will be deployed, not just what was written. The compiler is very good, but production only cares about the output.