Skip to content

Amazon S3 - Simple Storage Service

Chapter 16: Amazon S3 - Simple Storage Service

Section titled “Chapter 16: Amazon S3 - Simple Storage Service”

Amazon S3 (Simple Storage Service) is an object storage service offering industry-leading scalability, data availability, security, and performance.

S3 Overview
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | Amazon S3 | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Buckets | | Objects | | Storage | |
| | | | | | Classes | |
| | | | | | | |
| | - Global | | - Files | | - Standard| |
| | - Unique | | - Keys | | - IA | |
| | - Names | | - Metadata| | - Glacier | |
| +----------+ +----------+ +----------+ |
| |
| Buckets: Containers for objects (globally unique names) |
| Objects: Files + metadata (up to 5TB each) |
| Storage Classes: Different tiers for different use cases |
| |
+------------------------------------------------------------------+

S3 Bucket Structure
+------------------------------------------------------------------+
| |
| Bucket: my-bucket |
| +----------------------------------------------------------+ |
| | | |
| | Objects: | |
| | - images/photo1.jpg | |
| | - images/photo2.jpg | |
| | - documents/report.pdf | |
| | - logs/2024/01/app.log | |
| | - backup/data.tar.gz | |
| | | |
| | Object Components: | |
| | +----------------------------------------------------+ | |
| | | Key: images/photo1.jpg | | |
| | | Value: [Binary data] | | |
| | | Version ID: 123456789 | | |
| | | Metadata: | | |
| | | - Content-Type: image/jpeg | | |
| | | - Last-Modified: 2024-01-15T10:00:00Z | | |
| | | - x-amz-meta-custom: value | | |
| | | Tags: | | |
| | | - Environment: Production | | |
| | | - Owner: Team-A | | |
| | +----------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
| Key Concepts: |
| - Key: Unique identifier within bucket |
| - Prefix: Folder-like structure (images/, logs/) |
| - Delimiter: Usually / (forward slash) |
| |
+------------------------------------------------------------------+
S3 URL Formats
+------------------------------------------------------------------+
| |
| Virtual-Hosted Style (Recommended) |
| +----------------------------------------------------------+ |
| | https://bucket-name.s3.region.amazonaws.com/key | |
| | | |
| | Example: | |
| | https://my-bucket.s3.us-east-1.amazonaws.com/images/photo.jpg
| +----------------------------------------------------------+ |
| |
| Path Style (Legacy) |
| +----------------------------------------------------------+ |
| | https://s3.region.amazonaws.com/bucket-name/key | |
| | | |
| | Example: | |
| | https://s3.us-east-1.amazonaws.com/my-bucket/images/photo.jpg
| +----------------------------------------------------------+ |
| |
| S3 Access Point |
| +----------------------------------------------------------+ |
| | https://access-point-alias.s3-accesspoint.region.amazonaws.com
| | | |
| | Example: | |
| | https://my-ap-123456789012.s3-accesspoint.us-east-1.amazonaws.com
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

S3 Storage Classes
+------------------------------------------------------------------+
| |
| 1. S3 Standard (General Purpose) |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Frequently accessed data | |
| | Availability: 99.99% | |
| | Durability: 99.999999999% (11 9s) | |
| | Min Storage: None | |
| | Retrieval: Immediate | |
| | AZs: 3+ | |
| +----------------------------------------------------------+ |
| |
| 2. S3 Intelligent-Tiering |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Unknown access patterns | |
| | Tiers: | |
| | - Frequent Access (auto) | |
| | - Infrequent Access (30 days no access) | |
| | - Archive (90 days no access) | |
| | - Deep Archive (180 days no access) | |
| | Monitoring fee: Small monthly fee | |
| | Retrieval: Immediate | |
| +----------------------------------------------------------+ |
| |
| 3. S3 Standard-IA (Infrequent Access) |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Less frequent access | |
| | Availability: 99.9% | |
| | Min Storage: 30 days | |
| | Min Object Size: 128KB | |
| | Retrieval: Per-GB fee | |
| | Retrieval Time: Immediate | |
| +----------------------------------------------------------+ |
| |
| 4. S3 One Zone-IA |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Infrequently accessed, non-critical | |
| | Availability: 99.5% | |
| | AZs: 1 (less resilient) | |
| | Min Storage: 30 days | |
| | Min Object Size: 128KB | |
| | Retrieval: Immediate | |
| +----------------------------------------------------------+ |
| |
| 5. S3 Glacier Instant Retrieval |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Archive, immediate access | |
| | Min Storage: 90 days | |
| | Min Object Size: 128KB | |
| | Retrieval: Milliseconds | |
| | Cost: Lower storage, higher retrieval | |
| +----------------------------------------------------------+ |
| |
| 6. S3 Glacier Flexible Retrieval (Formerly Glacier) |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Long-term archive | |
| | Min Storage: 90 days | |
| | Retrieval Options: | |
| | - Expedited: 1-5 minutes | |
| | - Standard: 3-5 hours | |
| | - Bulk: 5-12 hours | |
| +----------------------------------------------------------+ |
| |
| 7. S3 Glacier Deep Archive |
| +----------------------------------------------------------+ |
| | | |
| | Use Case: Long-term retention (7+ years) | |
| | Min Storage: 180 days | |
| | Retrieval Options: | |
| | - Standard: 12 hours | |
| | - Bulk: 48 hours | |
| | Cost: Lowest storage cost | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Storage Class Comparison Table
+------------------------------------------------------------------+
| |
| Class | Access | Min Storage | Retrieval |
| ----------------|-------------|-------------|------------------|
| Standard | Frequent | None | Immediate |
| Intelligent | Variable | None | Immediate |
| Standard-IA | Infrequent | 30 days | Immediate |
| One Zone-IA | Infrequent | 30 days | Immediate |
| Glacier Inst. | Archive | 90 days | Milliseconds |
| Glacier Flex. | Archive | 90 days | 1-12 hours |
| Deep Archive | Long-term | 180 days | 12-48 hours |
| |
+------------------------------------------------------------------+

S3 Versioning
+------------------------------------------------------------------+
| |
| Versioning States |
| +----------------------------------------------------------+ |
| | | |
| | 1. Not Enabled (default) | |
| | - No versioning | |
| | | |
| | 2. Enabled | |
| | - All versions preserved | |
| | - Delete marker for deletes | |
| | | |
| | 3. Suspended | |
| | - New objects get null version ID | |
| | - Existing versions preserved | |
| | | |
| +----------------------------------------------------------+ |
| |
| Versioning Example |
| +----------------------------------------------------------+ |
| | | |
| | Object: document.txt | |
| | | |
| | Upload v1: | |
| | Key: document.txt | |
| | Version ID: 111111 | |
| | Content: "Version 1" | |
| | | |
| | Upload v2: | |
| | Key: document.txt | |
| | Version ID: 222222 | |
| | Content: "Version 2" | |
| | | |
| | Delete: | |
| | Key: document.txt | |
| | Version ID: 333333 (Delete Marker) | |
| | | |
| | Result: | |
| | - GET document.txt -> 404 (delete marker) | |
| | - GET document.txt?versionId=111111 -> "Version 1" | |
| | - GET document.txt?versionId=222222 -> "Version 2" | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
S3 Lifecycle Policies
+------------------------------------------------------------------+
| |
| Lifecycle Rules |
| +----------------------------------------------------------+ |
| | | |
| | Rule 1: Transition to IA | |
| | +----------------------------------------------------+ | |
| | | Filter: prefix "logs/" | | |
| | | Transition: | | |
| | | - After 30 days -> Standard-IA | | |
| | | - After 90 days -> Glacier Instant | | |
| | | - After 365 days -> Glacier Deep Archive | | |
| | +----------------------------------------------------+ | |
| | | |
| | Rule 2: Expiration | |
| | +----------------------------------------------------+ | |
| | | Filter: prefix "temp/" | | |
| | | Expiration: | | |
| | | - After 7 days -> Delete | | |
| | +----------------------------------------------------+ | |
| | | |
| | Rule 3: Versioned Objects | |
| | +----------------------------------------------------+ | |
| | | Filter: prefix "archive/" | | |
| | | Noncurrent Version Transitions: | | |
| | | - After 30 days -> Standard-IA | | |
| | | - After 90 days -> Glacier | | |
| | | Noncurrent Version Expiration: | | |
| | | - After 365 days -> Delete | | |
| | | Delete Marker Expiration: | | |
| | | - After 7 days -> Remove delete marker | | |
| | +----------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
S3 Encryption Options
+------------------------------------------------------------------+
| |
| Server-Side Encryption (SSE) |
| +----------------------------------------------------------+ |
| | | |
| | SSE-S3 (Amazon Managed Keys) | |
| | +----------------------------------------------------+ | |
| | | - AES-256 encryption | | |
| | | - AWS manages keys | | |
| | | - Free | | |
| | | - Header: x-amz-server-side-encryption: AES256 | | |
| | +----------------------------------------------------+ | |
| | | |
| | SSE-KMS (KMS Managed Keys) | |
| | +----------------------------------------------------+ | |
| | | - KMS Customer Master Key (CMK) | | |
| | | - Audit trail via CloudTrail | | |
| | | - Key rotation support | | |
| | | - Cost: KMS API calls | | |
| | | - Header: x-amz-server-side-encryption: aws:kms | | |
| | +----------------------------------------------------+ | |
| | | |
| | SSE-C (Customer Provided Keys) | |
| | +----------------------------------------------------+ | |
| | | - You provide encryption key | | |
| | | - AWS manages encryption | | |
| | | - HTTPS required | | |
| | | - AWS does not store the key | | |
| | +----------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
| Client-Side Encryption |
| +----------------------------------------------------------+ |
| | | |
| | - Encrypt data before uploading | |
| | - Use AWS Encryption SDK | |
| | - Full control over encryption process | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
S3 Access Control
+------------------------------------------------------------------+
| |
| Bucket Policy (Resource-based Policy) |
| +----------------------------------------------------------+ |
| | { | |
| | "Version": "2012-10-17", | |
| | "Statement": [ | |
| | { | |
| | "Sid": "PublicReadGetObject", | |
| | "Effect": "Allow", | |
| | "Principal": "*", | |
| | "Action": "s3:GetObject", | |
| | "Resource": "arn:aws:s3:::my-bucket/*" | |
| | }, | |
| | { | |
| | "Sid": "AllowCloudFrontAccess", | |
| | "Effect": "Allow", | |
| | "Principal": { | |
| | "Service": "cloudfront.amazonaws.com" | |
| | }, | |
| | "Action": "s3:GetObject", | |
| | "Resource": "arn:aws:s3:::my-bucket/*", | |
| | "Condition": { | |
| | "StringEquals": { | |
| | "AWS:SourceArn": "arn:aws:cloudfront::..." | |
| | } | |
| | } | |
| | } | |
| | ] | |
| | } | |
| +----------------------------------------------------------+ |
| |
| ACL (Access Control List) - Legacy |
| +----------------------------------------------------------+ |
| | | |
| | Grantees: | |
| | - Owner (Full Control) | |
| | - AuthenticatedUsers (AWS accounts) | |
| | - AllUsers (Public) | |
| | - LogDelivery (S3 logs) | |
| | | |
| | Permissions: | |
| | - READ | |
| | - WRITE | |
| | - READ_ACP | |
| | - WRITE_ACP | |
| | - FULL_CONTROL | |
| | | |
| | Note: Use bucket policies instead of ACLs | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

S3 Select
+------------------------------------------------------------------+
| |
| Purpose: Query objects using SQL |
| |
| Traditional Approach: |
| +----------------------------------------------------------+ |
| | 1. Download entire object (GBs) | |
| | 2. Parse locally | |
| | 3. Extract needed data | |
| +----------------------------------------------------------+ |
| |
| S3 Select Approach: |
| +----------------------------------------------------------+ |
| | 1. Send SQL query to S3 | |
| | 2. S3 filters and returns only matching data | |
| | 3. Reduced data transfer and cost | |
| +----------------------------------------------------------+ |
| |
| Example Query: |
| +----------------------------------------------------------+ |
| | SELECT name, age FROM s3object s | |
| | WHERE s.age > 25 | |
| | LIMIT 10 | |
| +----------------------------------------------------------+ |
| |
| Supported Formats: |
| - CSV, JSON, Parquet |
| - GZIP and BZIP2 compression |
| |
+------------------------------------------------------------------+
S3 Event Notifications
+------------------------------------------------------------------+
| |
| Event Types: |
| +----------------------------------------------------------+ |
| | - s3:ObjectCreated:* | |
| | - s3:ObjectCreated:Put | |
| | - s3:ObjectCreated:Post | |
| | - s3:ObjectCreated:Copy | |
| | - s3:ObjectCreated:CompleteMultipartUpload | |
| | - s3:ObjectRemoved:* | |
| | - s3:ObjectRemoved:Delete | |
| | - s3:ObjectRestore:* | |
| | - s3:ObjectRestore:Completed | |
| | - s3:ReducedRedundancyLostObject | |
| +----------------------------------------------------------+ |
| |
| Destinations: |
| +----------------------------------------------------------+ |
| | | |
| | S3 Event -> Lambda Function | |
| | S3 Event -> SNS Topic | |
| | S3 Event -> SQS Queue | |
| | S3 Event -> EventBridge | |
| | | |
| +----------------------------------------------------------+ |
| |
| Configuration Example: |
| +----------------------------------------------------------+ |
| | { | |
| | "LambdaFunctionConfigurations": [{ | |
| | "Id": "ImageProcessing", | |
| | "LambdaFunctionArn": "arn:aws:lambda:...", | |
| | "Events": ["s3:ObjectCreated:*"], | |
| | "Filter": { | |
| | "Key": { | |
| | "FilterRules": [{ | |
| | "Name": "prefix", | |
| | "Value": "images/" | |
| | }, { | |
| | "Name": "suffix", | |
| | "Value": ".jpg" | |
| | }] | |
| | } | |
| | } | |
| | }] | |
| | } | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
S3 Access Points
+------------------------------------------------------------------+
| |
| Purpose: Simplify access management for shared datasets |
| |
| Architecture: |
| +----------------------------------------------------------+ |
| | | |
| | Bucket: shared-data-bucket | |
| | +----------------------------------------------------+ | |
| | | | | |
| | | Access Point: finance-ap | | |
| | | +----------------------------------------------+ | | |
| | | | Policy: Allow finance-team | | | |
| | | | Prefix: finance/ | | | |
| | | | VPC: vpc-finance | | | |
| | | +----------------------------------------------+ | | |
| | | | | |
| | | Access Point: analytics-ap | | |
| | | +----------------------------------------------+ | | |
| | | | Policy: Allow analytics-team | | | |
| | | | Prefix: analytics/ | | | |
| | | | VPC: vpc-analytics | | | |
| | | +----------------------------------------------+ | | |
| | | | | |
| | +----------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
| Features: |
| - Unique DNS name per access point |
| - Dedicated access policy |
| - VPC endpoint support |
| - Block public access inheritance |
| |
+------------------------------------------------------------------+
S3 Object Lock (WORM)
+------------------------------------------------------------------+
| |
| Purpose: Write Once, Read Many (WORM) compliance |
| |
| Retention Modes: |
| +----------------------------------------------------------+ |
| | | |
| | Governance Mode: | |
| | - Most users cannot overwrite/delete | |
| | - Special permissions can override | |
| | - Use case: Prevent accidental deletion | |
| | | |
| | Compliance Mode: | |
| | - No one can overwrite/delete | |
| | - Including root user | |
| | - Use case: Regulatory compliance | |
| | | |
| +----------------------------------------------------------+ |
| |
| Retention Period: |
| +----------------------------------------------------------+ |
| | - Fixed duration (days or years) | |
| | - Can be extended | |
| | - Cannot be shortened (compliance mode) | |
| +----------------------------------------------------------+ |
| |
| Legal Hold: |
| +----------------------------------------------------------+ |
| | - Indefinite retention | |
| | - Until explicitly removed | |
| | - Requires s3:PutObjectLegalHold permission | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

# ============================================================
# S3 Bucket
# ============================================================
resource "aws_s3_bucket" "main" {
bucket = "my-unique-bucket-name"
tags = {
Name = "main-bucket"
}
}
# ============================================================
# Versioning
# ============================================================
resource "aws_s3_bucket_versioning" "main" {
bucket = aws_s3_bucket.main.id
versioning_configuration {
status = "Enabled"
}
}
# ============================================================
# Server-Side Encryption
# ============================================================
resource "aws_s3_bucket_server_side_encryption_configuration" "main" {
bucket = aws_s3_bucket.main.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3.arn
}
}
}
# ============================================================
# Block Public Access
# ============================================================
resource "aws_s3_bucket_public_access_block" "main" {
bucket = aws_s3_bucket.main.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# ============================================================
# Bucket Policy
# ============================================================
resource "aws_s3_bucket_policy" "main" {
bucket = aws_s3_bucket.main.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowSSLRequestsOnly"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.main.arn,
"${aws_s3_bucket.main.arn}/*"
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
},
{
Sid = "AllowCloudFrontAccess"
Effect = "Allow"
Principal = {
Service = "cloudfront.amazonaws.com"
}
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.main.arn}/*"
Condition = {
StringEquals = {
"AWS:SourceArn" = aws_cloudfront_distribution.main.arn
}
}
}
]
})
}
# ============================================================
# Lifecycle Configuration
# ============================================================
resource "aws_s3_bucket_lifecycle_configuration" "main" {
bucket = aws_s3_bucket.main.id
rule {
id = "transition-to-ia"
status = "Enabled"
filter {
prefix = "logs/"
}
transition {
days = 30
storage_class = "STANDARD_IA"
}
transition {
days = 90
storage_class = "GLACIER"
}
expiration {
days = 365
}
}
rule {
id = "versioned-objects"
status = "Enabled"
filter {
prefix = "archive/"
}
noncurrent_version_transition {
noncurrent_days = 30
storage_class = "STANDARD_IA"
}
noncurrent_version_transition {
noncurrent_days = 90
storage_class = "GLACIER"
}
noncurrent_version_expiration {
noncurrent_days = 365
}
}
}
# ============================================================
# S3 Access Point
# ============================================================
resource "aws_s3_access_point" "finance" {
bucket = aws_s3_bucket.main.id
name = "finance-access-point"
public_access_block_configuration {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowFinanceTeam"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::123456789012:role/FinanceRole"
}
Action = "s3:GetObject"
Resource = "${aws_s3_access_point.finance.arn}/object/finance/*"
}
]
})
}
# ============================================================
# S3 Event Notification
# ============================================================
resource "aws_s3_bucket_notification" "main" {
bucket = aws_s3_bucket.main.id
lambda_function {
lambda_function_arn = aws_lambda_function.image_processor.arn
events = ["s3:ObjectCreated:*"]
filter_prefix = "images/"
filter_suffix = ".jpg"
}
sqs {
id = "sqs-notification"
queue_arn = aws_sqs_queue.s3_events.arn
events = ["s3:ObjectCreated:*"]
filter_prefix = "uploads/"
}
}
# ============================================================
# S3 Object Lock Configuration
# ============================================================
resource "aws_s3_bucket_object_lock_configuration" "main" {
bucket = aws_s3_bucket.main.id
object_lock_enabled = "Enabled"
rule {
default_retention {
mode = "COMPLIANCE"
days = 365
}
}
}
# ============================================================
# S3 Replication Configuration
# ============================================================
resource "aws_s3_bucket_replication_configuration" "main" {
bucket = aws_s3_bucket.main.id
role = aws_iam_role.replication.arn
destination {
bucket = aws_s3_bucket.replica.arn
storage_class = "STANDARD"
}
rule {
id = "replication-rule"
status = "Enabled"
filter {}
delete_marker_replication {
status = "Enabled"
}
}
}
# Enable versioning for replication
resource "aws_s3_bucket_versioning" "replica" {
bucket = aws_s3_bucket.replica.id
versioning_configuration {
status = "Enabled"
}
}

S3 is the backbone of data storage in AWS. From CI/CD artifacts and Terraform state to log aggregation and backup, S3 is used everywhere in DevOps workflows.

S3 in DevOps Workflows
+------------------------------------------------------------------+
| |
| Core S3 Use Cases for DevOps: |
| |
| 1. CI/CD Artifact Storage |
| +----------------------------------------------------------+ |
| | - Build artifacts from CodeBuild/Jenkins | |
| | - Docker layer caching for faster builds | |
| | - Terraform state backend (with DynamoDB locking) | |
| +----------------------------------------------------------+ |
| |
| 2. Log Aggregation |
| +----------------------------------------------------------+ |
| | - CloudTrail logs for auditing | |
| | - VPC flow logs for network analysis | |
| | - ALB/CloudFront access logs | |
| +----------------------------------------------------------+ |
| |
| 3. Disaster Recovery |
| +----------------------------------------------------------+ |
| | - Cross-region replication for critical data | |
| | - Database backups with lifecycle policies | |
| | - Object Lock for compliance (WORM) | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Terminal window
# Install S3 tools
sudo pacman -S aws-cli-v2 jq
yay -S s3cmd
# Bucket cost analysis script
#!/bin/bash
# ~/bin/s3-cost-report.sh
set -euo pipefail
echo "=== S3 Bucket Size Report ==="
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
size=$(aws cloudwatch get-metric-statistics \
--namespace AWS/S3 \
--metric-name BucketSizeBytes \
--dimensions Name=BucketName,Value="$bucket" Name=StorageType,Value=StandardStorage \
--start-time "$(date -d '1 day ago' --iso-8601)" \
--end-time "$(date --iso-8601)" \
--period 86400 \
--statistics Average \
--query 'Datapoints[0].Average' \
--output text 2>/dev/null)
if [ "$size" != "None" ] && [ -n "$size" ]; then
size_gb=$(echo "scale=2; $size / 1073741824" | bc)
echo "$bucket: ${size_gb} GB"
fi
done | sort -t: -k2 -rn
# Sync with progress and exclusions
aws s3 sync ./build/ s3://my-deploy-bucket/releases/v1.2.3/ \
--exclude '*.log' \
--exclude '.git/*' \
--delete
# Find and clean old versions (cost savings)
aws s3api list-object-versions \
--bucket my-bucket \
--prefix logs/ \
--query 'Versions[?IsLatest==`false`].[Key,VersionId,LastModified,Size]' \
--output table | head -30

IssueCauseSolution
403 ForbiddenBucket policy / IAM denyingCheck bucket policy AND IAM policy, both must allow
404 Not FoundWrong bucket or key nameVerify region, bucket name, and exact object key
Slow uploadsLarge file, no multipartUse multipart upload for files >100MB
High S3 costsNo lifecycle policiesAdd lifecycle rules: IA after 30d, Glacier after 90d
Cross-account access deniedMissing bucket policy principalAdd cross-account IAM ARN to bucket policy
Replication not workingVersioning not enabledEnable versioning on BOTH source and destination
Terminal window
# Debug S3 access issues
# Check bucket policy
aws s3api get-bucket-policy --bucket my-bucket --output json | jq '.Policy | fromjson'
# Check if public access is blocked
aws s3api get-public-access-block --bucket my-bucket
# Test specific IAM permissions
aws s3api head-object --bucket my-bucket --key test-file.txt

  1. Q: Explain S3 storage classes and when to use each.

    • A: Standard for frequently accessed data. Intelligent-Tiering for unknown patterns (auto-moves between tiers). Standard-IA for infrequent access but fast retrieval (min 30 days). Glacier Instant for archive with instant retrieval. Glacier Flexible for 1-12 hour retrieval. Deep Archive for 12-48 hour retrieval (cheapest). Use lifecycle policies to automate transitions.
  2. Q: How would you secure an S3 bucket?

    • A: (1) Block Public Access at account level, (2) Enable SSE-KMS encryption, (3) Enforce SSL via bucket policy condition, (4) Enable versioning + MFA delete, (5) Use VPC endpoints for private access, (6) Enable CloudTrail data events for audit, (7) Apply least-privilege bucket policies, (8) Enable Object Lock for compliance data.
  1. Q: Design a cost-effective log storage strategy on S3.
    • A: Ingest logs to S3 Standard → lifecycle rule transitions to Standard-IA at 30 days → Glacier at 90 days → Deep Archive at 180 days → delete at 365 days. Enable S3 Intelligent-Tiering for unpredictable access. Use S3 Select/Athena to query logs without ETL. Enable Requester Pays for shared log buckets. Compress logs (gzip) before upload.

Exam Tip

  1. Bucket Names: Globally unique, 3-63 characters, lowercase
  2. Objects: Up to 5TB, key + value + metadata + version ID
  3. Storage Classes: Standard, Intelligent-Tiering, IA, One Zone-IA, Glacier
  4. Lifecycle Policies: Automate transitions and expiration
  5. Encryption: SSE-S3, SSE-KMS, SSE-C, Client-side
  6. Versioning: Preserves all versions, delete markers
  7. Object Lock: WORM, governance or compliance mode
  8. Access Points: Simplify access management for shared data
  9. S3 Select: Query objects with SQL, reduce data transfer
  10. Replication: CRR (cross-region), SRR (same-region)

Chapter 17: Amazon EBS - Elastic Block Store


Last Updated: March 2026