S3
S3 is durable object storage. Buckets hold objects; keys look like paths; each object has a content-type, metadata, optional versioning, and an ACL or bucket policy. The first AWS service most teams use, and one of the cheapest.
Upload, list, presigned URL, lifecycle
EXAMPLE
# 1) Create a bucket (region-specific)
aws s3 mb s3://my-bucket --region us-east-1
# Block public access by default (this is the safe default)
aws s3api put-public-access-block --bucket my-bucket --public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
# 2) Upload + download
aws s3 cp ./local.png s3://my-bucket/uploads/local.png
aws s3 cp s3://my-bucket/uploads/local.png ./out.png
# Sync a directory
aws s3 sync ./public/ s3://my-bucket/site/ --delete
# 3) List
aws s3 ls s3://my-bucket/ --recursive --human-readable --summarize
# 4) Versioning — recoverable from accidental overwrites
aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Enabled
# 5) Lifecycle policy — transition + expire (cost!)
cat > lifecycle.json <<JSON
{
"Rules": [{
"ID": "archive-logs",
"Status": "Enabled",
"Filter": { "Prefix": "logs/" },
"Transitions": [{ "Days": 30, "StorageClass": "GLACIER_IR" }],
"NoncurrentVersionExpiration": { "NoncurrentDays": 90 },
"Expiration": { "Days": 365 }
}]
}
JSON
aws s3api put-bucket-lifecycle-configuration --bucket my-bucket --lifecycle-configuration file://lifecycle.json
# 6) Server-side encryption (SSE-S3 default; SSE-KMS for per-key audit)
aws s3api put-bucket-encryption --bucket my-bucket \
--server-side-encryption-configuration '{
"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms"}}]
}'
# 7) Presigned URL — temporary, time-bound download/upload
aws s3 presign s3://my-bucket/private.pdf --expires-in 600
# Node — generate a presigned upload URL
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const s3 = new S3Client({ region: 'us-east-1' });
const cmd = new PutObjectCommand({
Bucket: 'my-bucket',
Key: `uploads/${randomUUID()}.png`,
ContentType: 'image/png',
});
const url = await getSignedUrl(s3, cmd, { expiresIn: 300 });
// Client PUTs to url — no AWS creds in the browser.
# 8) Static-site hosting (with CloudFront, not the legacy S3 website endpoint)
# - Upload site/ to bucket
# - Add a CloudFront distribution with OAC pointing at the bucket
# - Issue an ACM cert in us-east-1 for the domain
# - Configure default root object: index.html
# 9) Cost tips
# • Use S3 Intelligent-Tiering for unpredictable access patterns
# • Set a lifecycle rule for incomplete multipart uploads
# • Use S3 Storage Lens to find your top cost drivers
# • Cross-region replication doubles your costs — only when you need it
Why it matters
Block public access at the account AND bucket level by default. Most S3 leaks are buckets that were never meant to be public — the safer default is “deny” everywhere, then explicitly carve out CloudFront via Origin Access Control.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Object storage — unlimited, durable, cheap. aws s3 cp file.txt s3://my-bucket/Try it Yourself »
Exercise
Copy a local file to a bucket.
aws s3
file.txt s3://my-bucket/
Two letters.
Discussion
Loading…