What Is an S3 Bucket? Names, Regions, Objects, and Folder Structure
An S3 bucket is the top-level container that holds your objects in Amazon S3. Every file you store in S3 lives inside a bucket. The name, the region, and the access settings you choose at creation are permanent. This page explains how buckets work, how to name them correctly, and how to organise objects inside them.
Simple explanation
Analogy
Think of an S3 bucket like a postal address. You choose the address once, it belongs to you while you hold it, and everything you receive goes there. When you close the address, someone else can eventually use it. The things you stored there are gone when the address is released. The address (bucket name) is globally unique. The postcode (region) determines where it physically lives.
A bucket is a named, region-locked container. Objects go inside it. Folders are an illusion created by slashes in object names.
How S3 buckets work
This page covers general purpose buckets, which are the standard bucket type and the starting point for almost all S3 use cases. AWS has introduced other bucket types for specific workloads, but general purpose buckets are what you will use by default.
S3 is organised in three layers:
Bucket → Object → Key
A bucket is the top-level container. You create it once in a specific region and give it a globally unique name. Every object you store in S3 lives inside exactly one bucket.
An object is what you store: a file, an image, a log, a database backup. Every object has a key, which is its full name within the bucket. The key uniquely identifies the object.
A prefix is a shared string at the start of multiple keys. Prefixes look like folder paths but are just part of the key name.
Here is a concrete example. Suppose your bucket is named acme-corp-media-prod. It might contain these objects:
uploads/2025/january/report.pdf
uploads/2025/january/summary.csv
uploads/2025/february/report.pdf
thumbnails/user-123.jpg
thumbnails/user-456.jpgIn this example:
uploads/2025/january/report.pdfis the keyuploads/2025/is a prefixthumbnails/is a different prefix- There are no real folders, only keys that share a prefix
This flat structure matters when you write lifecycle policies, apply bucket or IAM policies, or query objects with S3 Select. All of those operations work on key prefixes, not directories.
Bucket vs object vs prefix
| Concept | What it is | Example |
|---|---|---|
| Bucket | Top-level container. One per region. Globally unique name. | acme-corp-media-prod |
| Object | The file you store. Identified by its key. Lives in exactly one bucket. | A PDF, an image, a log file |
| Key | The full name of the object within the bucket. This is the unique identifier. | uploads/2025/january/report.pdf |
| Prefix | A shared string at the start of multiple keys. Looks like a folder path. Not a real directory. | uploads/2025/ |
Bucket names: rules and examples
Bucket names go into a shared global namespace. No two AWS accounts worldwide can hold the same bucket name at the same time. When you delete a bucket, the name is released and eventually becomes available for anyone to claim. Names are not permanently locked, but you should choose them carefully and avoid deleting a bucket just to free up the name.
The naming rules for general purpose buckets:
- Between 3 and 63 characters long
- Only lowercase letters, numbers, and hyphens (periods are technically allowed but not recommended, see note below)
- Must start and end with a letter or number
- No underscores, spaces, or uppercase letters
- Cannot look like an IP address (e.g.
192.168.1.4) - Cannot begin with
xn--or end with-s3alias
Periods are valid in bucket names but cause problems with SSL certificate validation when using virtual-hosted-style URLs (e.g. my.bucket.name.s3.amazonaws.com). For a beginner-safe convention, stick to hyphens only. Underscores are not allowed because they are invalid in DNS hostnames.
Use the pattern {org}-{purpose}-{environment} or {org}-{purpose}-{environment}-{region}. Names that include your organisation, what the data is for, and which environment it belongs to are easy to read in billing reports, access logs, and CloudTrail.
| Good name | Bad name | Why bad |
|---|---|---|
acme-corp-uploads-prod | uploads | Generic, almost certainly already taken |
acme-corp-static-assets-prod | my-bucket | Not descriptive, likely taken |
acme-corp-backups-eu-west-2 | acme_corp_backups | Underscores not allowed |
acme-corp-data-pipeline-staging | AcmeProdBucket | Uppercase not allowed |
Bucket names and regions cannot be changed after creation. If you realise you named a bucket poorly, there is no rename operation. You must create a new bucket and migrate all your objects. Choose names that are specific to your organisation, environment, and purpose from the start.
Regions and why they matter
Every bucket belongs to a single AWS region. You choose the region at creation time and it cannot change later. This choice has real consequences.
Latency. If your application runs in eu-west-2 (London) and your bucket is in us-east-1 (Virginia), every upload and download crosses the Atlantic. Keeping your bucket and compute in the same region avoids this.
Transfer costs. Data transferred within the same region between S3 and other AWS services (EC2, Lambda) is generally free. Cross-region transfers incur egress charges that add up quickly at scale.
Compliance and data residency. If your data must remain within a specific country or jurisdiction, create buckets only in regions within that boundary. S3 does not automatically replicate data across regions. See S3 Security Best Practices for how to enforce this with policies.
When creating a bucket in us-east-1 via the AWS CLI, you do not pass —create-bucket-configuration. Every other region requires it. This is a historical oddity in the S3 API, not a feature.
# us-east-1: no LocationConstraint needed
aws s3api create-bucket \
--bucket acme-corp-uploads-prod \
--region us-east-1
# All other regions: LocationConstraint is required
aws s3api create-bucket \
--bucket acme-corp-uploads-prod \
--region eu-west-2 \
--create-bucket-configuration LocationConstraint=eu-west-2When to use one bucket vs multiple buckets
The default quota for general purpose buckets is 10,000 per AWS account, so you do not need to conserve buckets aggressively. The more useful question is what each bucket should contain.
One bucket with prefixes is usually enough when:
- You have one application with one access policy
- You want a single lifecycle rule to manage all data
- You want a single logging destination
- Your data all lives in the same region with the same compliance requirements
Separate buckets make sense when:
- Different environments. Keep
prod,staging, anddevin separate buckets. This prevents accidents and makes IAM policies simpler. You grant prod access to the prod bucket, not to a prefix within a shared bucket. - Different access boundaries. If one team should never see another team’s data, a separate bucket with its own policy is cleaner than prefix-based isolation.
- Different lifecycle or retention rules. Lifecycle policies apply at the bucket level or via prefix. If two data sets have fundamentally different retention requirements, separate buckets are easier to reason about.
- Static website hosting or access logging. These features are configured at the bucket level. If you need them for one data set but not another, a separate bucket keeps the configuration clean.
- Data residency or compliance separation. If one data set must stay in a specific region and another can go anywhere, keep them in separate buckets.
Multi-tenant applications should use a prefix like customers/{tenant-id}/ to separate tenant data within a single bucket. Creating a bucket per customer scatters your lifecycle rules, complicates billing visibility, and adds operational overhead for no meaningful security benefit that prefixes plus policies cannot provide.
S3 buckets vs folders and filesystems
S3 is object storage, not a filesystem. It does not have directories, inodes, or POSIX semantics.
Think of it this way
A traditional filesystem is like a filing cabinet with real drawers and folders inside. S3 is more like a spreadsheet with one column for every file name. Names that start with “invoices/2025/” appear together when you sort the column, but there is no physical folder. Delete one row and the others stay. There is no drawer to empty.
In a traditional filesystem (or Amazon EFS):
- Folders are real objects that exist on disk
- You can
mva directory and everything inside moves atomically - Listing a directory shows only the direct children
- A file has a path relative to its parent directory
In S3:
- There are no folders, only object keys
- What looks like a folder in the console is every object whose key starts with that prefix
- “Moving” a folder means copying every object to a new key and deleting the originals, one API call per object
- Listing with a prefix returns everything under that prefix, arbitrarily deep
# These are NOT folder contents. They are three separate objects.
images/profile/user-123.jpg (key)
images/profile/user-456.jpg (key)
images/thumbnails/user-123.jpg (key)The console shows images/ as a folder. If you delete images/profile/user-123.jpg, the “folder” images/profile/ disappears, because it was never a real object, just a shared prefix.
This matters for lifecycle rules, which match on key prefixes. It also matters when you expect filesystem-style operations and run into S3’s eventual-consistency model for large listings or bulk deletes.
If you need actual filesystem semantics such as shared mounts, file locking, or POSIX access, see S3 vs EFS to understand when EFS is the right choice.
Common mistakes
- Generic bucket names that are already taken. Names like
uploads,assets, orbackupare claimed in the global namespace. Use names that include your organisation and environment. If the name is taken, you cannot use it regardless of which AWS account you own. - Creating buckets in the wrong region. If your EC2 instances run in
eu-west-2and your S3 bucket is inus-east-1, every file transfer crosses regions, adding latency and incurring data transfer charges. Set the region correctly at creation time because it cannot be changed later. - Expecting to rename or move a bucket. There is no rename or move operation in S3. Bucket names and regions are permanent. If you need to change either, you must create a new bucket and copy all objects across.
- One bucket per customer in a multi-tenant app. Use a prefix like
customers/{tenant-id}/to separate tenant data within a single bucket. One bucket per customer scatters your lifecycle rules and complicates billing visibility for no real security benefit. - Treating prefixes like filesystem directories. Renaming a “folder” means copying and deleting every object under that prefix. There is no atomic folder rename in S3. Build your key naming strategy around this reality before you have millions of objects to reorganise.
Practical CLI examples
# List all buckets in your account
aws s3 ls
# Create a bucket in eu-west-2
aws s3api create-bucket \
--bucket acme-corp-uploads-prod \
--region eu-west-2 \
--create-bucket-configuration LocationConstraint=eu-west-2
# Block all public access (recommended default for most buckets)
aws s3api put-public-access-block \
--bucket acme-corp-uploads-prod \
--public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
# Enable versioning
aws s3api put-bucket-versioning \
--bucket acme-corp-uploads-prod \
--versioning-configuration Status=Enabled
# List all objects with a specific prefix
aws s3 ls s3://acme-corp-uploads-prod/customers/tenant-abc/ --recursive
# Delete an empty bucket
aws s3api delete-bucket --bucket acme-corp-uploads-prod --region eu-west-2
# Force-delete a bucket and all its contents (use with extreme caution)
aws s3 rb s3://acme-corp-uploads-prod --forceFor uploading objects, copying, and syncing directories, see Uploading Files to S3 with the AWS CLI.
If these commands return Access Denied, the issue is almost always a missing IAM permission or a bucket policy that is blocking access. See S3 Access Denied Errors for a structured debugging approach.
Summary
- A bucket is the top-level container for S3 objects. Every object lives in exactly one bucket, identified by a unique key.
- Bucket names are globally unique across all AWS accounts. Names become available again after deletion but should be chosen carefully from the start.
- Use lowercase letters, numbers, and hyphens only. Avoid periods and underscores. Include your org name, purpose, and environment.
- Buckets are tied to a single region and cannot be renamed or moved after creation. Region affects latency, egress cost, and data residency.
- S3 has no real directories. The folder structure you see is an illusion created by forward slashes in key names (prefixes).
- Default quota is 10,000 general purpose buckets per account. Use prefixes to separate tenants, not one bucket per customer.
Frequently asked questions
What is an S3 bucket in simple terms?
An S3 bucket is a named container that holds your files (called objects) in AWS. Every object you store in S3 lives inside a bucket. You choose the name, the region, and the access rules, and those choices stay fixed for the life of the bucket.
Do S3 buckets actually have folders?
No. S3 uses a flat namespace. What looks like folders in the AWS console are objects whose keys contain forward slashes. The prefix "reports/2025/" is part of the key name, not a real directory. There is no such thing as an empty folder in S3 unless an explicit zero-byte object is created to represent it.
How many buckets can I create?
The default quota for general purpose buckets is 10,000 per AWS account. This is high enough for almost any use case. If you need more, you can request an increase through the AWS Service Quotas console.
Can I rename or move a bucket to another region?
No. Bucket names and regions are set at creation and cannot be changed. If you need a different name or region, create a new bucket and migrate your data. There is no built-in rename or move operation.
Should I create one bucket per app, per environment, or per customer?
Usually one bucket per environment (prod, staging, dev) with prefixes to separate concerns within each environment. Separate buckets make sense when you need distinct access policies, lifecycle rules, logging destinations, or data residency requirements. Creating one bucket per customer is almost always the wrong default. Use prefixes instead.