S3 is the backbone of AWS storage: static assets, backups, data lakes, logs and artifacts all end up there.
Amazon S3 stores objects (any bytes, up to 5 TB each, plus metadata) under keys in buckets. Bucket names are globally unique across all AWS accounts, but each bucket lives in one Region and data stays there unless you replicate it. S3 is designed for 99.999999999% durability by storing data redundantly across AZs.
There are no real folders: reports/2026/q3.csv is one key, and the console just groups by / prefixes. S3 has strong read-after-write consistency: after a successful write, any read or list sees it.
Storage classes trade storage price against access cost and latency:
- Standard for frequently accessed data.
- Intelligent-Tiering moves objects between tiers automatically based on access, for unknown or changing patterns.
- Standard-IA and One Zone-IA are cheaper to store but charge per GB retrieved and have a 30-day minimum.
- Glacier Instant Retrieval, Glacier Flexible Retrieval and Glacier Deep Archive are for archives, with retrieval from milliseconds to hours.
Lifecycle rules transition objects to colder classes and expire them after a time, by prefix or tag. Versioning keeps every version of an object, protecting against overwrites and deletes (a delete adds a delete marker); pair it with lifecycle rules that expire old versions or costs grow silently.
Upload large files with multipart upload, which the CLI and SDKs do automatically above a threshold. Use aws s3 sync for directories and aws s3api for full control.
Example
B=acme-reports-111122223333
aws s3 mb "s3://$B" --region eu-west-1
aws s3 cp report.csv "s3://$B/reports/2026/10/report.csv"
aws s3 sync ./site "s3://$B/site" --delete # mirror a directory
aws s3 ls "s3://$B/reports/" --recursive --human-readable
# 2026-10-17 09:12:44 1.2 MiB reports/2026/10/report.csv
aws s3api put-bucket-versioning --bucket "$B" \
--versioning-configuration Status=Enabled
aws s3api put-bucket-lifecycle-configuration --bucket "$B" \
--lifecycle-configuration '{"Rules": [{
"ID": "tier-logs", "Status": "Enabled", "Filter": {"Prefix": "logs/"},
"Transitions": [{"Days": 30, "StorageClass": "STANDARD_IA"},
{"Days": 180, "StorageClass": "GLACIER"}],
"Expiration": {"Days": 730},
"NoncurrentVersionExpiration": {"NoncurrentDays": 30}}]}'Remember
- Buckets are regional with globally unique names; objects are key + bytes + metadata
- Prefixes are just key strings, not folders
- Choose storage classes by access pattern; automate with lifecycle rules
- Versioning protects data but needs noncurrent-version expiration
Watch out for
- Moving small, frequently read objects to Standard-IA, where retrieval fees and minimums cost more than they save.