AWS
S3
Cloud Storage
Automation
Bucket Management

How to remove multiple S3 buckets at once?

Master System Design with Codemia

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

Introduction

Amazon S3 does not offer one magic API call that deletes several buckets in a single request. In practice, "remove multiple buckets at once" means iterating over a list of bucket names and deleting each bucket carefully. The hard part is not the loop. The hard part is emptying the buckets correctly first, especially when versioning is enabled.

Buckets Must Be Empty Before Deletion

S3 will not delete a non-empty bucket. For ordinary non-versioned buckets, that means removing the objects. For versioned buckets, it also means removing:

  • object versions
  • delete markers

That is why a bulk-delete workflow needs to be explicit about the bucket state instead of assuming delete_bucket will take care of everything automatically.

Simple CLI Approach for Non-Versioned Buckets

If the buckets are non-versioned and you want a quick CLI approach, remove objects first and then remove the bucket:

bash
aws s3 rm s3://my-bucket-1 --recursive
aws s3 rb s3://my-bucket-1

For several buckets, you repeat the sequence for each one.

This is practical for a short list of disposable buckets, but it becomes fragile when:

  • versioning is enabled
  • the bucket list is large
  • you need error handling and logging

That is when an SDK-based approach is usually clearer.

A Safer Boto3 Example

Here is a Python example that deletes multiple non-versioned buckets:

python
1import boto3
2
3s3 = boto3.resource("s3")
4
5bucket_names = [
6    "example-bucket-one",
7    "example-bucket-two",
8]
9
10for name in bucket_names:
11    bucket = s3.Bucket(name)
12    bucket.objects.all().delete()
13    bucket.delete()
14    print(f"Deleted {name}")

This is much easier to integrate into a controlled cleanup workflow than clicking around the console.

It also makes it obvious that bucket deletion is a per-bucket process.

Versioned Buckets Need Extra Work

If versioning is enabled, deleting current objects is not enough. S3 still considers old versions and delete markers part of the bucket contents.

A version-aware example looks like this:

python
1import boto3
2
3s3 = boto3.resource("s3")
4
5def delete_versioned_bucket(bucket_name: str) -> None:
6    bucket = s3.Bucket(bucket_name)
7    bucket.object_versions.delete()
8    bucket.delete()
9
10
11delete_versioned_bucket("example-versioned-bucket")

That call removes all versions and delete markers exposed through object_versions, then deletes the bucket itself.

If you skip this step on a versioned bucket, the bucket deletion will fail because the bucket is still not empty.

Be Careful with Automation

Bulk bucket deletion is inherently destructive. Before running it, make sure you understand:

  • whether the buckets contain production data
  • whether object lock, retention, or lifecycle policies are involved
  • whether the bucket names might be reused by someone else later

S3 bucket names are globally unique. Once you delete a bucket, the name can eventually become available for reuse elsewhere. That is one reason production bucket cleanup deserves more care than temporary test environment cleanup.

Why the Console Is Usually Not Enough

The AWS console is fine for deleting one or two buckets. It is not great for repeated operational cleanup because:

  • it is manual
  • it is easy to click the wrong thing
  • it is harder to make the process auditable

For multiple buckets, CLI or SDK workflows are usually better because they let you:

  • review the bucket list
  • add logging
  • add approval steps
  • dry-run the list before deletion

That makes the process safer even when the underlying deletion is still one bucket at a time.

Handle Failures Explicitly

In a real cleanup script, do not assume every bucket deletion succeeds. Some common failure cases are:

  • access denied
  • bucket not empty because versioning was missed
  • object lock or retention configuration
  • typo in the bucket name

A minimal defensive pattern is:

python
1import boto3
2from botocore.exceptions import ClientError
3
4s3 = boto3.resource("s3")
5
6for name in ["bucket-a", "bucket-b"]:
7    try:
8        bucket = s3.Bucket(name)
9        bucket.object_versions.delete()
10        bucket.delete()
11        print(f"Deleted {name}")
12    except ClientError as exc:
13        print(f"Failed to delete {name}: {exc.response['Error']['Code']}")

That does not make the operation safe by itself, but it makes failures visible instead of silently ignored.

Common Pitfalls

The biggest mistake is trying to delete the bucket before emptying it. S3 requires the bucket to be empty first.

Another issue is forgetting that versioned buckets still contain old versions and delete markers even after current objects seem to be gone.

Developers also often treat bulk deletion as a single atomic operation. It is not. Each bucket can succeed or fail independently, so logging and review matter.

Finally, do not use an aggressive cleanup loop against bucket names you have not reviewed carefully. S3 bucket deletion is destructive and bucket names are globally significant.

Summary

  • S3 does not provide a single request that deletes multiple buckets in one shot.
  • Bulk deletion means iterating over bucket names and deleting each bucket safely.
  • Every bucket must be empty before deletion, including versions and delete markers for versioned buckets.
  • SDK or CLI workflows are usually safer and more repeatable than manual console cleanup.
  • Treat multi-bucket deletion as a destructive operation that needs explicit review and error handling.

Course illustration
Course illustration

All Rights Reserved.