Skip to content

S3 — Object Storage

Amazon Simple Storage Service (S3) is an object storage service. It stores data as objects (files) in buckets and is designed for 99.999999999% durability (11 nines). It’s used for backups, static websites, data lakes, and more.

Analogy: S3 is like a massive, infinitely expanding filing cabinet in the sky. Each cabinet is a bucket, each file is an object, and every file has a unique key (path).


sequenceDiagram
participant User as User/App
participant S3 as Amazon S3
participant Bucket as Bucket "my-app-assets"
participant Object as Object (key)
User->>S3: PUT /my-app-assets/images/photo.jpg
S3->>S3: Check bucket permissions (bucket policy)
alt Permission Denied
S3-->>User: 403 AccessDenied ❌
else Permission Allowed
S3->>Bucket: Store object
Note over Bucket: Assign version ID
Note over Bucket: Replicate across AZs
S3-->>User: 200 OK + ETag
User->>S3: GET /my-app-assets/images/photo.jpg
S3->>Bucket: Retrieve object by key
S3->>S3: Check: public? authenticated?
S3-->>User: Photo file ✅
end

1. Buckets — Top-level containers (globally unique name)

Terminal window
# Create a bucket
aws s3 mb s3://my-app-assets --region us-east-1
# List buckets
aws s3 ls

2. Objects — Files stored in buckets

Terminal window
# Upload an object
aws s3 cp index.html s3://my-app-assets/
# Upload with public-read permission
aws s3 cp logo.png s3://my-app-assets/images/ --acl public-read
# Download
aws s3 cp s3://my-app-assets/index.html ./downloads/
# List objects
aws s3 ls s3://my-app-assets/images/

3. Keys — The full path to an object

Bucket: my-app-assets
Keys (object paths):
images/photo.jpg ← "folder" simulated by key prefix
images/logo.png
docs/report.pdf
index.html

Data often starts in S3 Standard and moves to cheaper storage as it ages. This is called a lifecycle policy:

flowchart TB
Upload["📤 Object Uploaded"] --> Standard["S3 Standard<br/>💰 $$$<br/>Instant access"]
Standard -->|30 days| IA["S3 Standard-IA<br/>💰 $$<br/>Instant access,<br/>lower cost"]
IA -->|90 days| Glacier["S3 Glacier<br/>💰 $<br/>Min retrieval time"]
Glacier -->|365 days| Archive["Glacier Deep Archive<br/>💰 ¢<br/>12hr retrieval"]
Standard -->|Or directly| Intelligent["S3 Intelligent-Tiering<br/>Auto-moves data<br/>No access tracking needed"]
style Standard fill:#3b82f6,color:#fff
style IA fill:#059669,color:#fff
style Glacier fill:#f59e0b,color:#fff
style Archive fill:#ef4444,color:#fff
style Intelligent fill:#7c3aed,color:#fff

Lifecycle Rule Example (expire after 30 days):

{
"Rules": [{
"Id": "Move-to-IA",
"Status": "Enabled",
"Filter": {"Prefix": "logs/"},
"Transitions": [{
"Days": 30,
"StorageClass": "STANDARD_IA"
}]
}]
}

S3 security is layered — multiple protections stacked together:

flowchart TB
subgraph Layer1["Layer 1: Access Control"]
BP["Bucket Policies<br/>JSON rules for cross-account<br/>and public access"]
IAM["IAM Policies<br/>User/role-level permissions"]
ACL["ACLs<br/>Legacy basic allow/deny"]
end
subgraph Layer2["Layer 2: Encryption"]
SSE_S3["SSE-S3<br/>AWS-managed keys"]
SSE_KMS["SSE-KMS<br/>AWS KMS keys<br/>Auditing + controls"]
SSE_C["SSE-C<br/>Customer-provided keys"]
end
subgraph Layer3["Layer 3: Network Controls"]
BA["Block Public Access<br/>Account-level safety switch"]
VPCE["VPC Endpoint<br/>Access S3 without internet"]
end
subgraph Layer4["Layer 4: Monitoring"]
CloudTrail["CloudTrail<br/>API call logging"]
AccessLogs["Access Logs<br/>Request details"]
end
style Layer1 fill:#3b82f6,color:#fff
style Layer2 fill:#7c3aed,color:#fff
style Layer3 fill:#059669,color:#fff
style Layer4 fill:#ef4444,color:#fff

Best Practice Stack for Production:

  1. ✅ Block Public Access at account level (default on)
  2. ✅ Bucket policy with explicit deny for sensitive paths
  3. ✅ IAM roles for apps (never hard-code keys)
  4. ✅ SSE-KMS encryption for all objects
  5. ✅ CloudTrail + Access Logs enabled
  6. ✅ VPC Endpoint to keep traffic within AWS network

ClassDurabilityAvailabilityUse Case
S3 Standard11 9’s99.99%Frequently accessed, critical data
S3 Intelligent-Tiering11 9’s99.9%Unknown/fluctuating access patterns
S3 Standard-IA11 9’s99.9%Infrequent access, but rapid when needed
S3 One Zone-IA11 9’s99.5%Recreatable infrequent data
S3 Glacier11 9’s99.99%Archival (minutes to retrieve)
S3 Glacier Deep Archive11 9’s99.99%Long-term archive (hours to retrieve)

S3 can host static websites (HTML, CSS, JS):

Terminal window
# Enable static hosting
aws s3 website s3://my-app-assets --index-document index.html --error-document error.html
# Set bucket policy for public read
# (JSON policy allowing s3:GetObject for everyone)
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-app-assets/*"
}]
}

Your site is then available at: http://my-app-assets.s3-website-us-east-1.amazonaws.com


FeatureWhat It Does
Bucket policiesJSON rules for who can access the bucket
IAM policiesControl user-level access to S3
ACLsLegacy access control (simpler but less flexible)
Block public accessFirewall-level block — turn on by default!
Server-side encryptionSSE-S3, SSE-KMS, or SSE-C
VersioningKeep all versions of objects (protect against deletes)

  • S3 = object storage — store any file, any size, in buckets
  • Buckets have globally unique names; objects have keys (paths)
  • 11 nines durability — your data is incredibly safe
  • Can host static websites (HTML/CSS/JS) directly from S3
  • Storage classes let you save money by moving old data to Glacier
  • Always block public access by default and explicitly grant access when needed