1. Pengenalan AWS S3
Amazon Simple Storage Service (S3) adalah layanan object storage yang disediakan oleh Amazon Web Services (AWS). S3 dirancang untuk menyimpan dan mengambil data dalam jumlah besar â dari beberapa byte hingga 5 TB per object â dengan durability 99.999999999% (11 nines).
S3 menggunakan model key-value store dimana setiap object disimpan dengan key (nama file) unik di dalam sebuah bucket (container). S3 menawarkan virtually unlimited storage, high availability, dan berbagai fitur keamanan yang membuatnya menjadi standar industri untuk cloud storage.
Mengapa S3 Penting?
| Keunggulan | Penjelasan |
|---|---|
| Durability | 99.999999999% (11 nines) â data hampir tidak mungkin hilang |
| Availability | 99.99% â selalu bisa diakses kapan saja |
| Scalability | Tanpa batas â dari byte hingga exabytes |
| Security | Enkripsi at-rest dan in-transit, fine-grained access control |
| Performance | High throughput, low latency untuk semua storage class |
| Cost-Effective | Pay-as-you-go, tiered pricing berdasarkan akses pattern |
| Integration | Terintegrasi dengan seluruh layanan AWS (Lambda, CloudFront, dll) |
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â AWS S3 ARCHITECTURE â â â â ââââââââââââ ââââââââââââââââ âââââââââââââââââââââ â â â Client â â S3 API â â S3 Buckets â â â â (App/ âââââēâ (REST) âââââēâ â â â â Browser)â â â â ââââââââââââââââ â â â ââââââââââââ ââââââââââââââââ â â Bucket A â â â â â â /photos/ â â â â ââââââââââââ â â /documents/ â â â â â AWS CLI âââââââââââââââââââââââââēâ ââââââââââââââââ â â â ââââââââââââ â â â â â ââââââââââââââââ â â â ââââââââââââ â â Bucket B â â â â â AWS SDK âââââââââââââââââââââââââēâ â /backups/ â â â â â (boto3) â â â /logs/ â â â â ââââââââââââ â ââââââââââââââââ â â â âââââââââââââââââââââ â â â â Setiap object disimpan di minimal 3 AZ â â â Durability 99.999999999% (11 nines) â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Konsep dasar S3:
- Bucket â container untuk objects (seperti folder root)
- Object â file yang disimpan (data + metadata + key)
- Key â nama unik untuk setiap object di dalam bucket
- Region â lokasi geografis dimana bucket dibuat
- ARN â Amazon Resource Name untuk identifikasi resource
2. Membuat & Mengelola Bucket
Menggunakan AWS CLI
# Pastikan AWS CLI sudah dikonfigurasi aws configure # AWS Access Key ID: AKIAIOSFODNN7EXAMPLE # AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY # Default region name: ap-southeast-1 # Default output format: json # Buat bucket baru aws s3api create-bucket \ --bucket my-app-storage-2026 \ --region ap-southeast-1 \ --create-bucket-configuration LocationConstraint=ap-southeast-1 # List semua buckets aws s3 ls # Lihat detail bucket aws s3api get-bucket-location --bucket my-app-storage-2026 aws s3api head-bucket --bucket my-app-storage-2026 # Hapus bucket (harus kosong dulu) aws s3 rb s3://my-app-storage-2026 # Hapus bucket beserta semua isinya (FORCE) aws s3 rb s3://my-app-storage-2026 --force
Menggunakan Python (boto3)
import boto3
# Inisialisasi S3 client
s3 = boto3.client('s3', region_name='ap-southeast-1')
# Buat bucket
s3.create_bucket(
Bucket='my-app-storage-2026',
CreateBucketConfiguration={
'LocationConstraint': 'ap-southeast-1'
}
)
# List semua buckets
response = s3.list_buckets()
for bucket in response['Buckets']:
print(f"Bucket: {bucket['Name']}, Created: {bucket['CreationDate']}")
# Cek apakah bucket ada
def bucket_exists(bucket_name):
try:
s3.head_bucket(Bucket=bucket_name)
return True
except:
return False
print(bucket_exists('my-app-storage-2026')) # True
# Hapus bucket
s3.delete_bucket(Bucket='my-app-storage-2026')
Pengaturan Bucket Penting
# Block public access (keamanan default)
aws s3api put-public-access-block \
--bucket my-app-storage-2026 \
--public-access-block-configuration \
BlockPublicAcls=true,\
IgnorePublicAcls=true,\
BlockPublicPolicy=true,\
RestrictPublicBuckets=true
# Enable default encryption (AES-256)
aws s3api put-bucket-encryption \
--bucket my-app-storage-2026 \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms"
},
"BucketKeyEnabled": true
}
]
}'
# Enable access logging
aws s3api put-bucket-logging \
--bucket my-app-storage-2026 \
--bucket-logging-status '{
"LoggingEnabled": {
"TargetBucket": "my-s3-access-logs",
"TargetPrefix": "my-app-storage-2026/"
}
}'
# Set CORS configuration
aws s3api put-bucket-cors \
--bucket my-app-storage-2026 \
--cors-configuration '{
"CORSRules": [
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST"],
"AllowedOrigins": ["https://app.example.com"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
}'
3. Objects: Upload & Manage
Upload Files
# Upload file biasa
aws s3 cp ./photo.jpg s3://my-app-storage-2026/photos/photo.jpg
# Upload dengan metadata
aws s3 cp ./document.pdf s3://my-app-storage-2026/docs/ \
--metadata '{"author":"BeebaneLabs","category":"tutorial"}'
# Upload dengan content-type
aws s3 cp ./style.css s3://my-app-storage-2026/css/style.css \
--content-type "text/css"
# Upload seluruh direktori (recursive)
aws s3 sync ./public/ s3://my-app-storage-2026/website/ \
--exclude "*.tmp" \
--exclude ".git/*"
# Upload dengan progress
aws s3 cp ./large-file.zip s3://my-app-storage-2026/ \
--only-show-errors
# Upload dengan storage class
aws s3 cp ./archive.tar.gz s3://my-app-storage-2026/archives/ \
--storage-class GLACIER
# Multipart upload untuk file besar (>100MB)
aws s3 cp ./huge-file.zip s3://my-app-storage-2026/ \
--expected-size 5368709120
Download & Manage Files
# Download file
aws s3 cp s3://my-app-storage-2026/photos/photo.jpg ./downloaded.jpg
# Download seluruh direktori
aws s3 sync s3://my-app-storage-2026/website/ ./website-backup/
# List objects di bucket
aws s3 ls s3://my-app-storage-2026/
# List objects dengan prefix
aws s3 ls s3://my-app-storage-2026/photos/ --recursive
# List objects dengan ukuran
aws s3api list-objects-v2 \
--bucket my-app-storage-2026 \
--query 'Contents[].{Key: Key, Size: Size, Modified: LastModified}' \
--output table
# Hapus object
aws s3 rm s3://my-app-storage-2026/photos/old-photo.jpg
# Hapus semua objects dengan prefix
aws s3 rm s3://my-app-storage-2026/temp/ --recursive
# Pindahkan object (copy + delete)
aws s3 mv s3://my-app-storage-2026/temp/file.txt \
s3://my-app-storage-2026/archive/file.txt
# Copy antar bucket
aws s3 sync s3://source-bucket/ s3://destination-bucket/
Menggunakan Python (boto3)
import boto3
from botocore.exceptions import ClientError
s3 = boto3.client('s3')
BUCKET = 'my-app-storage-2026'
# Upload file
def upload_file(file_path, s3_key):
try:
s3.upload_file(
file_path, BUCKET, s3_key,
ExtraArgs={
'ContentType': 'image/jpeg',
'Metadata': {
'uploaded-by': 'beebanelabs',
'purpose': 'tutorial'
}
}
)
print(f"Uploaded: {s3_key}")
return True
except ClientError as e:
print(f"Error: {e}")
return False
# Upload dari memory (tanpa file)
import io
def upload_from_memory(data, s3_key, content_type='text/plain'):
s3.put_object(
Bucket=BUCKET,
Key=s3_key,
Body=data,
ContentType=content_type
)
# Download file
def download_file(s3_key, local_path):
s3.download_file(BUCKET, s3_key, local_path)
# List objects
def list_objects(prefix=''):
response = s3.list_objects_v2(
Bucket=BUCKET,
Prefix=prefix
)
for obj in response.get('Contents', []):
print(f"{obj['Key']} â {obj['Size']} bytes â {obj['LastModified']}")
# Generate presigned URL
def get_presigned_url(s3_key, expiration=3600):
url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': BUCKET, 'Key': s3_key},
ExpiresIn=expiration
)
return url
# Multipart upload untuk file besar
from boto3.s3.transfer import TransferConfig
config = TransferConfig(
multipart_threshold=1024 * 1024 * 100, # 100MB
max_concurrency=10,
multipart_chunksize=1024 * 1024 * 100
)
s3.upload_file(
'large-file.zip', BUCKET, 'uploads/large-file.zip',
Config=config
)
# Contoh penggunaan
upload_file('./photo.jpg', 'photos/photo.jpg')
download_file('photos/photo.jpg', './downloaded.jpg')
list_objects('photos/')
print(get_presigned_url('photos/photo.jpg'))
4. Storage Classes
AWS S3 menyediakan beberapa storage class yang dioptimalkan untuk berbagai use case dan akses pattern. Memilih storage class yang tepat bisa menghemat biaya secara signifikan.
Perbandingan Storage Classes
| Storage Class | Akses | Availability | Min Duration | Harga/GB/Bulan* | Best For |
|---|---|---|---|---|---|
| S3 Standard | Frequently | 99.99% | - | $0.023 | Hot data, web apps, content delivery |
| S3 Intelligent-Tiering | Unknown/Changing | 99.9% | - | $0.023 + monitoring | Unknown access patterns |
| S3 Standard-IA | Infrequent | 99.9% | 30 hari | $0.0125 | Backups, disaster recovery |
| S3 One Zone-IA | Infrequent | 99.5% | 30 hari | $0.01 | Recreatable data, secondary backups |
| S3 Glacier Instant | Rare (ms retrieval) | 99.9% | 90 hari | $0.004 | Archive yang perlu akses cepat |
| S3 Glacier Flexible | Archive (min 1min) | 99.99% | 90 hari | $0.0036 | Long-term archive |
| S3 Glacier Deep Archive | Cold (12hr retrieval) | 99.99% | 180 hari | $0.00099 | Compliance, long-term retention |
| S3 Express One Zone | Frequently (single AZ) | 99.95% | - | $0.16 | Ultra-low latency, ML training |
* Harga untuk region US East, bisa berbeda di region lain
Gunakan S3 Intelligent-Tiering jika Anda tidak yakin pola akses data. Layanan ini otomatis memindahkan data ke tier yang lebih murah jika tidak diakses selama 30 hari, tanpa biaya retrieval penalty.
# Upload dengan storage class tertentu aws s3 cp ./archive.tar.gz s3://my-bucket/ --storage-class GLACIER # Cek storage class object aws s3api head-object --bucket my-bucket --key archive.tar.gz \ --query 'StorageClass' # Pindahkan object ke storage class berbeda (copy ke diri sendiri) aws s3api copy-object \ --bucket my-bucket \ --key archive.tar.gz \ --copy-source my-bucket/archive.tar.gz \ --storage-class STANDARD_IA \ --metadata-directive COPY
5. Versioning
Versioning memungkinkan Anda menyimpan multiple versi dari setiap object. Ini sangat penting untuk melindungi data dari penghapusan atau overwrite yang tidak disengaja.
# Enable versioning
aws s3api put-bucket-versioning \
--bucket my-app-storage-2026 \
--versioning-configuration Status=Enabled
# Cek status versioning
aws s3api get-bucket-versioning --bucket my-app-storage-2026
# {
# "Status": "Enabled",
# "MFADelete": "Disabled"
# }
# List semua versi object
aws s3api list-object-versions \
--bucket my-app-storage-2026 \
--prefix "photos/photo.jpg"
# {
# "Versions": [
# {"Key": "photos/photo.jpg", "VersionId": "v3_abc123", ...},
# {"Key": "photos/photo.jpg", "VersionId": "v2_def456", ...},
# {"Key": "photos/photo.jpg", "VersionId": "v1_ghi789", ...}
# ]
# }
# Download versi spesifik
aws s3api get-object \
--bucket my-app-storage-2026 \
--key photos/photo.jpg \
--version-id v2_def456 \
./photo-v2.jpg
# Hapus versi spesifik (permanent delete)
aws s3api delete-object \
--bucket my-app-storage-2026 \
--key photos/photo.jpg \
--version-id v3_abc123
# Suspend versioning (tidak menghapus versi lama)
aws s3api put-bucket-versioning \
--bucket my-app-storage-2026 \
--versioning-configuration Status=Suspended
MFA Delete
# Enable MFA Delete (membutuhkan root account) # Memerlukan MFA token untuk menghapus versi atau mengubah versioning aws s3api put-bucket-versioning \ --bucket my-app-storage-2026 \ --versioning-configuration Status=Enabled,MFADelete=Enabled \ --mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456"
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â S3 VERSIONING â â â â Bucket: my-app-storage-2026 â â Versioning: Enabled â â â â Key: photos/photo.jpg â â ââââââââââââââââââââââââââââââââââââââââââââââ â â â v3 (latest) â content_v3.jpg â 2026-06-26â â â â v2 â content_v2.jpg â 2026-06-20â â â â v1 â content_v1.jpg â 2026-06-15â â â ââââââââââââââââââââââââââââââââââââââââââââââ â â â â Key: documents/report.pdf (DELETED) â â ââââââââââââââââââââââââââââââââââââââââââââââ â â â v3 (delete â [delete marker]â 2026-06-26â â â â marker) â â â â â â v2 â report_v2.pdf â 2026-06-20â â â â v1 â report_v1.pdf â 2026-06-15â â â ââââââââââââââââââââââââââââââââââââââââââââââ â â â â Delete marker bisa dihapus untuk "restore" object â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
6. Lifecycle Management
Lifecycle rules mengotomatiskan transisi object antar storage class dan penghapusan object yang sudah tidak diperlukan. Ini sangat penting untuk mengelola biaya storage.
{
"Rules": [
{
"ID": "TransitionToIA",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
},
{
"Days": 365,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 730
}
},
{
"ID": "CleanupTempFiles",
"Status": "Enabled",
"Filter": {
"Prefix": "temp/"
},
"Expiration": {
"Days": 7
}
},
{
"ID": "ManageOldVersions",
"Status": "Enabled",
"Filter": {},
"NoncurrentVersionTransitions": [
{
"NoncurrentDays": 30,
"StorageClass": "STANDARD_IA"
},
{
"NoncurrentDays": 90,
"StorageClass": "GLACIER"
}
],
"NoncurrentVersionExpiration": {
"NoncurrentDays": 365
}
},
{
"ID": "RemoveIncompleteMultipart",
"Status": "Enabled",
"Filter": {},
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 7
}
}
]
}
# Terapkan lifecycle rules aws s3api put-bucket-lifecycle-configuration \ --bucket my-app-storage-2026 \ --lifecycle-configuration file://lifecycle.json # Lihat lifecycle rules aws s3api get-bucket-lifecycle-configuration \ --bucket my-app-storage-2026 # Hapus lifecycle rules aws s3api delete-bucket-lifecycle \ --bucket my-app-storage-2026
7. IAM Policies & Bucket Policies
Keamanan S3 diatur melalui dua jenis policy: IAM Policy (attached ke user/role) dan Bucket Policy (attached ke bucket). Keduanya bekerja bersama untuk menentukan siapa yang bisa mengakses apa.
Bucket Policy â Contoh Umum
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAppReadAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/app-role"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-storage-2026",
"arn:aws:s3:::my-app-storage-2026/*"
]
},
{
"Sid": "DenyPublicAccess",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-app-storage-2026",
"arn:aws:s3:::my-app-storage-2026/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
},
{
"Sid": "AllowCloudFrontAccess",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-app-storage-2026/public/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1234567890"
}
}
}
]
}
# Terapkan bucket policy aws s3api put-bucket-policy \ --bucket my-app-storage-2026 \ --policy file://bucket-policy.json # Lihat bucket policy aws s3api get-bucket-policy --bucket my-app-storage-2026 # Hapus bucket policy aws s3api delete-bucket-policy --bucket my-app-storage-2026
IAM Policy untuk User/Role
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Access",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-app-storage-2026",
"arn:aws:s3:::my-app-storage-2026/uploads/*",
"arn:aws:s3:::my-app-storage-2026/public/*"
]
},
{
"Sid": "DenyDeleteProduction",
"Effect": "Deny",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::my-app-storage-2026/production/*"
}
]
}
Jangan pernah membuat bucket S3 public kecuali Anda benar-benar tahu apa yang Anda lakukan. Banyak kebocoran data terjadi karena bucket S3 yang tidak sengaja di-public-kan. Selalu gunakan BlockPublicAcls dan akses melalui CloudFront atau presigned URLs.
8. Presigned URLs
Presigned URLs memungkinkan Anda memberikan akses sementara ke object S3 tanpa perlu membuat object tersebut public. URL ini memiliki waktu kedaluwarsa dan bisa digunakan untuk upload maupun download.
Menggunakan AWS CLI
# Generate presigned URL untuk download (berlaku 1 jam) aws s3 presign s3://my-app-storage-2026/photos/photo.jpg \ --expires-in 3600 # https://my-app-storage-2026.s3.ap-southeast-1.amazonaws.com/photos/photo.jpg?... # Generate presigned URL untuk download (berlaku 7 hari) aws s3 presign s3://my-app-storage-2026/documents/report.pdf \ --expires-in 604800 # Generate presigned URL untuk upload aws s3 presign s3://my-app-storage-2026/uploads/new-file.jpg \ --expires-in 3600 # Gunakan URL untuk upload via curl curl -X PUT \ -H "Content-Type: image/jpeg" \ --data-binary @photo.jpg \ "https://presigned-url-here"
Menggunakan Python (boto3)
import boto3
from botocore.config import Config
s3 = boto3.client('s3',
region_name='ap-southeast-1',
config=Config(signature_version='s3v4')
)
BUCKET = 'my-app-storage-2026'
# Generate presigned URL untuk GET (download)
def generate_download_url(key, expires_in=3600):
url = s3.generate_presigned_url(
'get_object',
Params={
'Bucket': BUCKET,
'Key': key,
'ResponseContentDisposition': f'attachment; filename="{key.split("/")[-1]}"'
},
ExpiresIn=expires_in
)
return url
# Generate presigned URL untuk PUT (upload)
def generate_upload_url(key, content_type='application/octet-stream', expires_in=3600):
url = s3.generate_presigned_url(
'put_object',
Params={
'Bucket': BUCKET,
'Key': key,
'ContentType': content_type
},
ExpiresIn=expires_in
)
return url
# Generate presigned POST (untuk browser upload â lebih fleksibel)
def generate_presigned_post(key, content_type='image/jpeg', max_size=10*1024*1024):
conditions = [
['content-length-range', 1, max_size],
['starts-with', '$Content-Type', content_type.split('/')[0]]
]
fields = {
'Content-Type': content_type,
'x-amz-meta-uploaded-by': 'beebanelabs'
}
response = s3.generate_presigned_post(
Bucket=BUCKET,
Key=key,
Fields=fields,
Conditions=conditions,
ExpiresIn=3600
)
return response
# Returns: {'url': 'https://...', 'fields': {...}}
# Contoh penggunaan
download_url = generate_download_url('photos/photo.jpg', expires_in=7200)
upload_url = generate_upload_url('uploads/new-photo.jpg')
post_data = generate_presigned_post('uploads/user-avatar.jpg')
print(f"Download URL: {download_url}")
print(f"Upload URL: {upload_url}")
print(f"POST URL: {post_data['url']}")
print(f"POST Fields: {post_data['fields']}")
Browser Upload dengan Presigned POST
// Upload file langsung dari browser ke S3
async function uploadToS3(file) {
// 1. Dapatkan presigned POST dari backend
const response = await fetch('/api/get-upload-url', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type
})
});
const { url, fields } = await response.json();
// 2. Upload langsung ke S3
const formData = new FormData();
Object.entries(fields).forEach(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
const uploadResponse = await fetch(url, {
method: 'POST',
body: formData
});
if (uploadResponse.ok) {
console.log('Upload berhasil!');
} else {
console.error('Upload gagal');
}
}
// Gunakan
document.getElementById('fileInput').addEventListener('change', (e) => {
uploadToS3(e.target.files[0]);
});
9. Static Website Hosting
S3 bisa digunakan untuk meng-host static website (HTML, CSS, JavaScript) tanpa perlu server. Dipadukan dengan CloudFront untuk CDN global dan custom domain.
# Enable static website hosting aws s3 website s3://my-website-bucket \ --index-document index.html \ --error-document error.html # Upload website files aws s3 sync ./public/ s3://my-website-bucket/ \ --acl public-read # Set content types aws s3 cp ./public/index.html s3://my-website-bucket/ \ --content-type "text/html" --acl public-read aws s3 cp ./public/css/style.css s3://my-website-bucket/css/ \ --content-type "text/css" --acl public-read aws s3 cp ./public/js/app.js s3://my-website-bucket/js/ \ --content-type "application/javascript" --acl public-read # Dapatkan website URL echo "Website URL: http://my-website-bucket.s3-website-ap-southeast-1.amazonaws.com"
Redirect Rules
<!-- website-redirect-rules.xml -->
<RoutingRules>
<RoutingRule>
<Condition>
<KeyPrefixEquals>old-page/</KeyPrefixEquals>
</Condition>
<Redirect>
<ReplaceKeyPrefixWith>new-page/</ReplaceKeyPrefixWith>
<HttpRedirectCode>301</HttpRedirectCode>
</Redirect>
</RoutingRule>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName>app.example.com</HostName>
<ReplaceKeyWith>index.html</ReplaceKeyWith>
</Redirect>
</RoutingRule>
</RoutingRules>
10. Encryption & Keamanan
Enkripsi di S3
| Enkripsi | Penjelasan | Kapan Digunakan |
|---|---|---|
| SSE-S3 | S3 manage encryption keys (AES-256) | Kebanyakan use case standar |
| SSE-KMS | AWS KMS manage keys (audit trail) | Compliance, audit requirement |
| SSE-C | Customer provide encryption keys | Kontrol penuh atas keys |
| Client-Side | Enkripsi sebelum upload ke S3 | Zero-trust, end-to-end encryption |
# Set default encryption (SSE-S3)
aws s3api put-bucket-encryption \
--bucket my-app-storage-2026 \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}'
# Upload dengan KMS encryption
aws s3 cp ./sensitive-data.csv s3://my-app-storage-2026/secure/ \
--sse aws:kms \
--sse-kms-key-id alias/my-s3-key
# Upload dengan AES-256 encryption
aws s3 cp ./data.csv s3://my-app-storage-2026/ \
--sse AES256
# Enable Object Lock (WORM â Write Once Read Many)
# Berguna untuk compliance
aws s3api put-object-lock-configuration \
--bucket my-app-storage-2026 \
--object-lock-configuration '{
"ObjectLockEnabled": true,
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Days": 365
}
}
}'
# Enable Transfer Acceleration (upload cepat via edge locations)
aws s3api put-bucket-accelerate-configuration \
--bucket my-app-storage-2026 \
--accelerate-configuration Status=Enabled
# Enable server access logging
aws s3api put-bucket-logging \
--bucket my-app-storage-2026 \
--bucket-logging-status '{
"LoggingEnabled": {
"TargetBucket": "my-s3-logs",
"TargetPrefix": "access-logs/"
}
}'
11. Best Practices
Keamanan
| Praktik | Rekomendasi |
|---|---|
| Block Public Access | Selalu aktifkan Block Public Access di level bucket |
| Enkripsi Default | Aktifkan SSE-S3 atau SSE-KMS sebagai default encryption |
| Enforce HTTPS | Tambahkan bucket policy yang menolak request non-HTTPS |
| Versioning | Selalu aktifkan versioning untuk bucket production |
| MFA Delete | Aktifkan MFA Delete untuk bucket kritis |
| Access Logging | Aktifkan server access logging untuk audit |
| Least Privilege | Berikan permission seminimal mungkin sesuai kebutuhan |
| Object Lock | Gunakan untuk data compliance (WORM) |
Biaya & Performance
- Gunakan lifecycle rules untuk transisi data ke storage class yang lebih murah
- Hapus incomplete multipart upload secara otomatis
- Gunakan S3 Intelligent-Tiering jika pola akses tidak diketahui
- Gunakan CloudFront sebagai CDN untuk akses global yang cepat
- Gunakan S3 Transfer Acceleration untuk upload lintas benua
- Monitor biaya dengan AWS Cost Explorer dan S3 Storage Lens
- Gunakan prefix naming yang baik untuk high-throughput workloads
Naming Conventions
# Prefix yang baik (mudah di-manage)
photos/2026/06/26/photo.jpg
documents/reports/quarterly-report-q2-2026.pdf
users/{user_id}/avatars/avatar.jpg
backups/database/2026-06-26-dump.sql.gz
logs/app/2026/06/26/app-log-001.gz
# Hindari
PHOTO.JPG # Tidak ada hierarchy
a/b/c/d/e/f/file.txt # Terlalu dalam
file with spaces.txt # Spasi menyulitkan
S3 dirancang untuk durability 99.999999999% (11 nines) yang berarti jika Anda menyimpan 10 juta object, statistiknya hanya 1 object yang hilang per 10.000 tahun. Tapi ini bukan backup â tetap gunakan cross-region replication untuk disaster recovery.
12. Quiz Pemahaman
1. Berapa durability S3 Standard?
2. Apa itu Presigned URL?
3. Apa fungsi S3 Versioning?
4. Storage class mana yang paling murah untuk data yang sangat jarang diakses?
5. Mengapa bucket S3 sebaiknya tidak di-public-kan?