AWS S3 Buckets

By Vishvesh Patel · DevOps EngineerUpdated September 15, 2026

Creating and configuring S3 buckets. Global naming rules, the us-east-1 exception, and how to delete a bucket that will not delete.

A bucket is the top-level container for objects. Creating one takes a single command; creating one you will not regret takes about six settings.

Naming rules

Bucket names are globally unique across every AWS account, not just yours. That is why obvious names fail. Someone claimed logs and backups in 2006.

RuleDetail
Length3, 63 characters
CharactersLowercase letters, numbers, hyphens, dots
Start and endA letter or number
Not permittedUppercase, underscores, formatted as an IP address
Prefixes to avoidxn--, sthree-
Suffixes to avoid-s3alias, --ol-s3

Avoid dots entirely. A bucket name containing a dot breaks virtual-hosted-style HTTPS access, because the wildcard certificate does not match multi-level subdomains, which produces a TLS error that looks nothing like a naming problem.

The practical convention is to include your account ID or organisation name:

acme-artifacts-111122223333
acme-prod-logs-eu-west-1

Creating one

aws s3api create-bucket \
  --bucket acme-artifacts-111122223333 \
  --region eu-west-1 \
  --create-bucket-configuration LocationConstraint=eu-west-1

us-east-1 is the exception. It must not have a LocationConstraint, and passing one fails with InvalidLocationConstraint:

aws s3api create-bucket --bucket acme-artifacts-111122223333 --region us-east-1

This inconsistency exists because us-east-1 was the original region and its API behaviour predates the concept.

Region matters more than people expect

A bucket lives in one region and the data stays there. Three consequences:

  • Latency: a bucket far from your compute is slow.
  • Cost: cross-region requests and transfer are charged more than same-region.
  • Compliance: data residency requirements are satisfied by region choice.

Put the bucket in the same region as whatever reads it most.

The settings to apply at creation

Some of these cannot be added later, and the rest are tedious to retrofit.

BUCKET=acme-artifacts-111122223333

# 1. Block all public access. Four settings, all on
aws s3api put-public-access-block --bucket $BUCKET \
  --public-access-block-configuration \
  "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

# 2. Disable ACLs. The mechanism behind most historic S3 exposures
aws s3api put-bucket-ownership-controls --bucket $BUCKET \
  --ownership-controls 'Rules=[{ObjectOwnership=BucketOwnerEnforced}]'

# 3. Versioning. Cannot be undone, so decide deliberately
aws s3api put-bucket-versioning --bucket $BUCKET \
  --versioning-configuration Status=Enabled

# 4. Encryption with a bucket key to keep KMS costs sane
aws s3api put-bucket-encryption --bucket $BUCKET \
  --server-side-encryption-configuration '{
    "Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"},"BucketKeyEnabled":true}]}'

# 5. Lifecycle, at minimum, clean up failed multipart uploads
aws s3api put-bucket-lifecycle-configuration --bucket $BUCKET \
  --lifecycle-configuration file://lifecycle.json

Good news on defaults: Block Public Access is on by default for new buckets, ACLs are disabled by default under Bucket owner enforced ownership, and SSE-S3 encryption is applied automatically. The commands above are worth running anyway to make the intent explicit in code rather than relying on a default that could differ across accounts.

The lifecycle rule for incomplete multipart uploads belongs on every bucket. Failed uploads leave parts billed as storage that never appear in a listing, and teams find them years later as an unexplained cost.

Object Lock is creation-only

If you need genuine immutability, ransomware protection, regulatory retention, Object Lock must be enabled when the bucket is created. It cannot be added afterwards, and retrofitting means creating a new bucket and copying everything.

aws s3api create-bucket \
  --bucket acme-backups-111122223333 \
  --region eu-west-1 \
  --create-bucket-configuration LocationConstraint=eu-west-1 \
  --object-lock-enabled-for-bucket

Folders do not exist

The console shows folders, but S3 has none. logs/2026/09/app.log is a single flat key that happens to contain slashes.

ExpectationReality
Deleting a folderDeleting every object under that prefix
An empty folderDoes not exist unless a zero-byte object was created
Renaming a folderCopying every object and deleting the originals
Listing a folderA prefix scan, which is slow over millions of keys

Prefixes do matter for one real reason: S3 scales request rate per prefix, at roughly 3,500 writes and 5,500 reads per second each. A high-throughput workload writing everything under one prefix will throttle.

Deleting a bucket

A bucket must be empty before it can be deleted, which is a useful accident-preventer.

# Delete objects and the bucket in one step
aws s3 rb s3://$BUCKET --force

That --force deletes every object first. On a versioned bucket it is not enough. Versions and delete markers remain, and rb still fails:

# Remove all versions
aws s3api delete-objects --bucket $BUCKET --delete "$(aws s3api list-object-versions \
  --bucket $BUCKET --output json \
  --query '{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"

# Remove all delete markers
aws s3api delete-objects --bucket $BUCKET --delete "$(aws s3api list-object-versions \
  --bucket $BUCKET --output json \
  --query '{Objects: DeleteMarkers[].{Key:Key,VersionId:VersionId}}')"

aws s3api delete-bucket --bucket $BUCKET

A gentler alternative for large buckets is a lifecycle rule expiring everything, then deleting the bucket a day later. S3 does the deletion in the background at no request cost.

Note that a deleted bucket name is not immediately reusable, and in a different region it may take time to become available.

Go deeper in this section

Sub-topicWhat you will learn
S3 PermissionsBucket policies, IAM and public access
S3 VersioningVersion history, delete markers, recovery

Quick reference

TaskCommand
Createaws s3api create-bucket --bucket <b> --region <r> --create-bucket-configuration LocationConstraint=<r>
Create in us-east-1aws s3api create-bucket --bucket <b> --region us-east-1
List bucketsaws s3 ls
Bucket regionaws s3api get-bucket-location --bucket <b>
Size and object countaws s3 ls s3://<b> --recursive --summarize --human-readable
Public access settingsaws s3api get-public-access-block --bucket <b>
Empty and deleteaws s3 rb s3://<b> --force
Orphaned uploadsaws s3api list-multipart-uploads --bucket <b>

Key takeaways

  • Bucket names are globally unique across all of AWS. Include your account ID.
  • Avoid dots in names; they break virtual-hosted-style HTTPS with a confusing TLS error.
  • us-east-1 must omit LocationConstraint: every other region requires it.
  • Object Lock can only be enabled at creation. Decide up front for anything holding backups.
  • Add an AbortIncompleteMultipartUpload lifecycle rule to every bucket.
  • There are no folders: keys are flat strings, and prefixes affect request-rate scaling.
  • aws s3 rb --force does not empty a versioned bucket. Versions and delete markers need removing first.

Check your understanding

Exercise

A create that fails in one region

The same create-bucket command works in eu-west-1 but fails with InvalidLocationConstraint in us-east-1. Why?

Exercise

A bucket that will not delete

aws s3 rb s3://my-bucket --force reports the bucket is not empty, but a listing shows no objects. What is going on?


Frequently Asked Questions

Why does my S3 bucket name fail with "already exists"?

Bucket names are globally unique across every AWS account, so a short or obvious name was almost certainly claimed years ago, and you get the same error whether it belongs to you or to a stranger. Names must also be 3 to 63 characters, lowercase, and DNS-compatible. Including your account ID or organisation prefix, as in acme-artifacts-111122223333, makes collisions essentially impossible and also makes ownership obvious when browsing a long list.

Why does creating a bucket in us-east-1 behave differently?

us-east-1 was the original S3 region and predates the LocationConstraint parameter, so the API treats it as the implicit default and rejects an explicit value with InvalidLocationConstraint. Every other region requires the parameter. Scripts written for one region and reused for another hit this constantly, so it is worth handling explicitly if you provision across regions.

Should I use dots in bucket names?

No. A name containing a dot breaks virtual-hosted-style HTTPS access, because AWS's wildcard certificate does not match multi-level subdomains, so requests fail with a TLS error that gives no hint about naming. Dots were historically used to match a custom domain for static website hosting, but the modern approach is CloudFront in front of a private bucket, which removes the reason entirely. Use hyphens.

What settings should I apply to a new S3 bucket?

Block Public Access on all four settings, Bucket owner enforced ownership to disable ACLs, default encryption with a bucket key enabled, and a lifecycle rule that aborts incomplete multipart uploads. Most of these are now defaults for new buckets, but applying them explicitly in your infrastructure code makes the intent visible and protects against differences between accounts. Decide about versioning and Object Lock at creation, since Object Lock cannot be added later and versioning cannot be undone.

How do I delete a bucket that will not empty?

If versioning is or was ever enabled, aws s3 rb --force is not enough. It removes current objects but leaves noncurrent versions and delete markers, which block deletion while being invisible in a normal listing. Delete them explicitly using list-object-versions piped into delete-objects for both Versions and DeleteMarkers. For very large buckets, a lifecycle rule expiring everything is cheaper and easier: S3 removes the objects in the background at no request cost, and the bucket deletes cleanly a day or two later.

Do folders exist in S3?

No. The console renders folders for convenience, but a key like logs/2026/app.log is a single flat string containing slashes. Deleting a folder means deleting every object with that prefix, renaming one means copying and deleting every object, and an empty folder only exists if someone created a zero-byte object to represent it. Prefixes do matter for performance, though: S3 scales request rate per prefix, so spreading high-volume writes across prefixes avoids throttling.

Continue Learning

Explore Related Topics

When it breaks

Related Resources