AWS
CloudFormation
S3
Bucket Deletion
Infrastructure Management

Can I force CloudFormation to delete non-empty S3 Bucket?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

CloudFormation does not have a built-in "force delete this non-empty S3 bucket" switch. If a bucket still contains objects, stack deletion fails until the bucket is emptied first, because S3 itself requires the bucket to be empty before it can be removed.

Why CloudFormation Stops at a Non-Empty Bucket

This behavior is deliberate. A stack delete should not silently destroy stored data unless you have explicitly built that behavior into the stack. From CloudFormation's perspective, a bucket with objects is not ready for deletion, so the stack enters a failed delete state and leaves the bucket behind.

That means the real question is not whether CloudFormation can be forced. The real question is how you want the emptying step to happen.

The Simple Answer: Empty the Bucket First

If this is a one-off or an infrequent teardown, empty the bucket yourself and then retry the stack deletion:

bash
aws s3 rm s3://my-stack-bucket --recursive
aws cloudformation delete-stack --stack-name my-stack

If bucket versioning is enabled, deleting current objects is not enough. You also need to remove object versions and delete markers, otherwise the bucket is still not truly empty.

For ad hoc cleanup, manual emptying is often the safest path because it makes the destructive step explicit.

Automating Cleanup With a Custom Resource

If the stack is temporary and automatic teardown is expected, the usual CloudFormation solution is a custom resource backed by Lambda. The Lambda runs during stack deletion, lists the bucket contents, removes objects and versions, and then lets CloudFormation continue.

A simplified template shape looks like this:

yaml
1Resources:
2  AppBucket:
3    Type: AWS::S3::Bucket
4
5  EmptyBucketFunction:
6    Type: AWS::Lambda::Function
7    Properties:
8      Runtime: python3.12
9      Handler: index.handler
10      Role: arn:aws:iam::123456789012:role/empty-bucket-role
11      Timeout: 300
12      Code:
13        ZipFile: |
14          import boto3
15
16          s3 = boto3.client("s3")
17
18          def handler(event, context):
19              bucket = event["ResourceProperties"]["BucketName"]
20              paginator = s3.get_paginator("list_object_versions")
21              for page in paginator.paginate(Bucket=bucket):
22                  objects = []
23                  for item in page.get("Versions", []):
24                      objects.append({"Key": item["Key"], "VersionId": item["VersionId"]})
25                  for item in page.get("DeleteMarkers", []):
26                      objects.append({"Key": item["Key"], "VersionId": item["VersionId"]})
27                  if objects:
28                      s3.delete_objects(Bucket=bucket, Delete={"Objects": objects})
29              return {"Status": "SUCCESS"}

In a real stack you would also add the custom resource wiring and proper CloudFormation response handling, but the important idea is clear: CloudFormation itself does not empty the bucket, so you add a resource that does.

CDK Users See the Same Rule

If you use AWS CDK, options such as automatic object deletion are implemented by generating supporting resources under the hood. They are not a hidden native CloudFormation flag. That is a useful mental model when debugging stack behavior.

Be Careful With Production Data

Automated deletion is convenient for test stacks, ephemeral environments, and scratch buckets. It is much more dangerous for production or audit data. In those cases, a failed delete can be a helpful safety mechanism rather than an inconvenience.

A common production pattern is:

  • keep the bucket with a retention policy
  • empty it manually through an approved process
  • delete only after the data lifecycle is complete

That gives humans a chance to confirm that nothing important is about to disappear.

Common Pitfalls

The most common mistake is deleting only current objects in a versioned bucket. Old versions and delete markers still keep the bucket non-empty.

Another issue is building a cleanup Lambda without the right IAM permissions. It needs permission to list and delete the bucket contents.

Teams also treat automatic emptying as harmless in every environment. It is safe only when data loss is acceptable by design.

Summary

  • CloudFormation cannot natively force-delete a non-empty S3 bucket.
  • The bucket must be emptied first, either manually or through a custom resource.
  • Versioned buckets require deletion of object versions and delete markers too.
  • Automatic cleanup is useful for ephemeral stacks but risky for important data.
  • A failed stack delete is often a sign that CloudFormation is protecting data, not misbehaving.

Course illustration
Course illustration

All Rights Reserved.