The CDK Stack That Would Not Delete
cdk destroy on a throwaway stack, and CloudFormation sat in DELETE_IN_PROGRESS for twenty minutes before landing on DELETE_FAILED. The console gave me one line of reason, on one resource, with no hint about the other nine that had already rolled back.
Three causes cover almost every case.
A bucket with objects in it. S3 refuses to delete a non-empty bucket, and CDK’s default RemovalPolicy.RETAIN on stateful resources means it often doesn’t even try. Set both properties, because the removal policy alone is not enough:
new s3.Bucket(this, 'Assets', { removalPolicy: cdk.RemovalPolicy.DESTROY, autoDeleteObjects: true,});autoDeleteObjects provisions a Lambda-backed custom resource that empties the bucket first. It only works alongside DESTROY, and CDK will tell you so at synth time.
Log groups that came back. Lambda creates /aws/lambda/<function> on first invocation. That group belongs to nobody in your template, so it survives the delete, and the next deploy fails with “already exists” when CDK tries to create it properly. Declare the group yourself with a removal policy and the cycle stops.
Network interfaces. A Lambda in a VPC leaves hyperplane ENIs behind, and the security group can’t go until they do. This one resolves on its own, but it takes up to forty minutes. If the stack failed on a security group with a dependency violation, wait before you start deleting things by hand.
When you just need it gone
A stack in DELETE_FAILED can be deleted again while skipping the resources that refuse to go:
aws cloudformation delete-stack \ --stack-name my-stack \ --retain-resources MyBucket,MyLogGroupThe stack disappears. The retained resources stay in your account, orphaned, and now they’re your problem to clean up manually. Take the logical ids from the failure events, not from a guess.
The habit I picked up from this: set RemovalPolicy.DESTROY at the moment you create a resource you know is temporary, not at the moment you try to delete it. By then the stack is already stuck.
