AWS S3 Lifecycle Rules, Replication and Intelligent Tiering
Published: June 6, 2026 • 15 min read
Amazon S3 is far more than a simple object store. It ships with a rich set of data-management primitives — lifecycle automation, multi-region replication, access-pattern-aware tiering, immutability controls, and versioning — that together let you cut storage costs by 70–90% while simultaneously improving durability and compliance posture. This guide walks through every one of those features with production-ready CLI commands and JSON policies you can paste straight into your pipelines.
1. S3 Storage Classes — Choosing the Right Tier
AWS offers eight storage classes, each tuned for a different access frequency and cost profile. Picking the wrong class for your data is one of the most common causes of unexpectedly high S3 bills.
| Storage Class | Use Case | Availability SLA | Min Storage Duration | Retrieval Cost | Approx. Price (per GB/mo) |
|---|---|---|---|---|---|
| S3 Standard | Frequently accessed data | 99.99% | None | Free | $0.023 |
| S3 Intelligent-Tiering | Unknown or changing access | 99.9% | None | Free (monitoring fee applies) | $0.023 (frequent) / $0.0125 (infrequent) |
| S3 Standard-IA | Infrequently accessed, rapid retrieval | 99.9% | 30 days | $0.01/GB | $0.0125 |
| S3 One Zone-IA | Infrequent access, reproducible data | 99.5% | 30 days | $0.01/GB | $0.01 |
| S3 Glacier Instant Retrieval | Archive, ms retrieval | 99.9% | 90 days | $0.03/GB | $0.004 |
| S3 Glacier Flexible Retrieval | Archive, 1–12 hr retrieval | 99.99% | 90 days | $0.01/GB (standard) | $0.0036 |
| S3 Glacier Deep Archive | Long-term archive, 12–48 hr retrieval | 99.99% | 180 days | $0.02/GB | $0.00099 |
| S3 Express One Zone | Single-AZ, sub-10ms latency | 99.95% | None | Free | $0.16 |
The general ladder is: Standard → Standard-IA → Glacier Instant → Glacier Flexible → Glacier Deep Archive. Lifecycle rules automate the descent; Intelligent-Tiering handles it automatically when access patterns are unpredictable.
2. S3 Lifecycle Rules
Lifecycle rules are bucket-level policies that tell S3 to automatically transition objects to cheaper storage classes or delete them after a set number of days. They are free to configure and run server-side with no compute cost to you.
2.1 Transition Actions
A transition action moves objects to a different storage class after a specified number of days since object creation (or since they became non-current for versioned buckets).
2.2 Expiration Actions
Expiration actions permanently delete objects (or non-current versions) after a threshold is reached. For versioned buckets, expiration adds a delete marker rather than immediately removing data; an additional NoncurrentVersionExpiration rule cleans up old versions.
2.3 Creating a Lifecycle Policy via AWS CLI
The following JSON policy implements a common cost-optimization ladder: move to Standard-IA after 30 days, Glacier Instant after 90 days, Glacier Deep Archive after 365 days, then delete after 2555 days (7 years). Non-current versions are pruned after 90 days.
# lifecycle-policy.json
{
"Rules": [
{
"ID": "CostOptimizationLadder",
"Status": "Enabled",
"Filter": {
"Prefix": "data/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER_IR"
},
{
"Days": 365,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 2555
},
"NoncurrentVersionTransitions": [
{
"NoncurrentDays": 30,
"StorageClass": "STANDARD_IA"
},
{
"NoncurrentDays": 60,
"StorageClass": "GLACIER_IR"
}
],
"NoncurrentVersionExpiration": {
"NoncurrentDays": 90,
"NewerNoncurrentVersions": 3
},
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 7
}
}
]
}
Apply the policy with:
# Apply lifecycle policy to a bucket
aws s3api put-bucket-lifecycle-configuration \
--bucket my-production-bucket \
--lifecycle-configuration file://lifecycle-policy.json
# Verify the policy was applied
aws s3api get-bucket-lifecycle-configuration \
--bucket my-production-bucket
NewerNoncurrentVersions field (added in 2023) lets you keep the N most recent non-current versions regardless of age. Use it to ensure you always have rollback points while still deleting very old versions.
2.4 Lifecycle Rule Filters
Filters can target objects by prefix, tag, or object size range. You can combine a prefix with tags using And:
"Filter": {
"And": {
"Prefix": "logs/",
"Tags": [
{ "Key": "Environment", "Value": "production" }
],
"ObjectSizeGreaterThan": 131072
}
}
This targets only objects under logs/ tagged as production that are larger than 128 KB — preventing small objects (which have per-object overhead that makes IA tiers uneconomical) from being transitioned prematurely.
3. S3 Versioning
Versioning preserves every overwrite and delete of an object. Once enabled on a bucket it cannot be fully disabled — only suspended (existing versions are retained). Versioning is a prerequisite for replication and Object Lock.
3.1 Enable Versioning
# Enable versioning
aws s3api put-bucket-versioning \
--bucket my-production-bucket \
--versioning-configuration Status=Enabled
# Check versioning status
aws s3api get-bucket-versioning \
--bucket my-production-bucket
# List all versions of objects in a bucket
aws s3api list-object-versions \
--bucket my-production-bucket \
--prefix data/reports/ \
--query 'Versions[*].{Key:Key,VersionId:VersionId,LastModified:LastModified}'
3.2 MFA Delete
MFA Delete adds a second factor requirement before permanently deleting object versions or changing the versioning state. It can only be enabled by the bucket owner using root credentials:
# Enable MFA Delete (requires root credentials and MFA device serial + TOTP code)
aws s3api put-bucket-versioning \
--bucket my-production-bucket \
--versioning-configuration Status=Enabled,MFADelete=Enabled \
--mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device 123456"
3.3 Lifecycle Rules for Versioned Buckets
In versioned buckets use NoncurrentVersionTransition and NoncurrentVersionExpiration (covered in section 2.3) alongside the standard Transitions and Expiration rules. Also add an ExpiredObjectDeleteMarker rule to clean up stale delete markers that accumulate when all versions of an object have been deleted:
{
"Rules": [
{
"ID": "CleanDeleteMarkers",
"Status": "Enabled",
"Filter": {},
"Expiration": {
"ExpiredObjectDeleteMarker": true
}
}
]
}
4. S3 Intelligent-Tiering
S3 Intelligent-Tiering is a storage class that automatically moves objects between access tiers based on real usage patterns. Unlike manual lifecycle rules, it requires zero configuration of transition thresholds.
4.1 How It Works
- Frequent Access tier: Default for newly uploaded objects. Cost identical to S3 Standard ($0.023/GB).
- Infrequent Access tier: Objects not accessed for 30 consecutive days are moved here. Cost $0.0125/GB.
- Archive Instant Access tier: Objects not accessed for 90 days. Cost $0.004/GB. Retrieval in milliseconds.
- Archive Access tier (opt-in): Configurable 90–730 days. Cost $0.0036/GB. Retrieval 3–5 hours.
- Deep Archive Access tier (opt-in): Configurable 180–730 days. Cost $0.00099/GB. Retrieval 12 hours.
4.2 Monitoring Fee
Intelligent-Tiering charges a per-object monitoring fee of $0.0025 per 1,000 objects per month. This makes it uneconomical for objects smaller than 128 KB — the monitoring cost outweighs any storage savings. Use lifecycle rules with an ObjectSizeGreaterThan filter to move only larger objects into Intelligent-Tiering.
4.3 Enabling Intelligent-Tiering on a Bucket
# Upload an object directly into Intelligent-Tiering
aws s3 cp large-dataset.parquet s3://my-production-bucket/data/ \
--storage-class INTELLIGENT_TIERING
# Configure bucket-level Intelligent-Tiering with archive tiers enabled
aws s3api put-bucket-intelligent-tiering-configuration \
--bucket my-production-bucket \
--id FullArchiveConfig \
--intelligent-tiering-configuration '{
"Id": "FullArchiveConfig",
"Status": "Enabled",
"Filter": {
"Prefix": "analytics/"
},
"Tierings": [
{
"Days": 90,
"AccessTier": "ARCHIVE_ACCESS"
},
{
"Days": 180,
"AccessTier": "DEEP_ARCHIVE_ACCESS"
}
]
}'
# Verify the configuration
aws s3api get-bucket-intelligent-tiering-configuration \
--bucket my-production-bucket \
--id FullArchiveConfig
4.4 When to Use Intelligent-Tiering
Intelligent-Tiering is the right choice when:
- Access patterns are unknown or change over time (e.g., data lake with ad-hoc queries)
- Objects are larger than 128 KB
- You cannot tolerate the operational overhead of manually tuning lifecycle thresholds
- You want millisecond retrieval even for archived objects (Archive Instant Access)
5. Cross-Region Replication (CRR)
CRR automatically copies objects from a source bucket in one AWS region to a destination bucket in a different region. It provides geographic redundancy, low-latency reads for globally distributed applications, and compliance with data residency requirements.
5.1 Prerequisites
- Versioning must be enabled on both source and destination buckets
- An IAM role granting S3 permission to replicate on your behalf
- Source and destination buckets must be owned by the same account (for same-account CRR) or the destination bucket policy must grant access (for cross-account CRR)
5.2 IAM Role for Replication
# s3-replication-trust-policy.json — trust policy for the IAM role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
# s3-replication-permissions.json — permissions policy attached to the role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetReplicationConfiguration",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::source-bucket"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObjectVersionForReplication",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging"
],
"Resource": "arn:aws:s3:::source-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags"
],
"Resource": "arn:aws:s3:::destination-bucket/*"
}
]
}
# Create the IAM role
aws iam create-role \
--role-name S3ReplicationRole \
--assume-role-policy-document file://s3-replication-trust-policy.json
# Attach the permissions policy
aws iam put-role-policy \
--role-name S3ReplicationRole \
--policy-name S3ReplicationPermissions \
--policy-document file://s3-replication-permissions.json
5.3 Replication Configuration JSON
# replication-config.json
{
"Role": "arn:aws:iam::123456789012:role/S3ReplicationRole",
"Rules": [
{
"ID": "ReplicateAllToDR",
"Status": "Enabled",
"Filter": {
"Prefix": ""
},
"Destination": {
"Bucket": "arn:aws:s3:::destination-bucket-us-west-2",
"StorageClass": "STANDARD_IA",
"ReplicationTime": {
"Status": "Enabled",
"Time": {
"Minutes": 15
}
},
"Metrics": {
"Status": "Enabled",
"EventThreshold": {
"Minutes": 15
}
}
},
"DeleteMarkerReplication": {
"Status": "Enabled"
},
"SourceSelectionCriteria": {
"SseKmsEncryptedObjects": {
"Status": "Enabled"
}
}
}
]
}
# Apply the replication configuration
aws s3api put-bucket-replication \
--bucket source-bucket \
--replication-configuration file://replication-config.json
# Verify replication status of a specific object
aws s3api head-object \
--bucket source-bucket \
--key data/important-file.parquet \
--query 'ReplicationStatus'
5.4 S3 Replication Time Control (RTC)
Standard replication has no SLA — objects are replicated within minutes but AWS does not guarantee a maximum time. S3 Replication Time Control (RTC) provides an SLA of 99.99% of objects replicated within 15 minutes. RTC is enabled in the replication config as shown above (ReplicationTime with Minutes: 15). It costs an additional $0.015 per GB replicated and an additional $0.01 per million objects.
Metrics block in the config above). CloudWatch metrics then expose ReplicationLatency and BytesPendingReplication for monitoring.
6. Same-Region Replication (SRR)
SRR uses the same configuration mechanism as CRR but both buckets live in the same AWS region. The setup is identical — versioning on both buckets, an IAM replication role, and a replication configuration JSON.
6.1 SRR Use Cases
- Log aggregation: Multiple application buckets replicate into a single central logging bucket in the same region for unified analysis.
- Compliance copy: Regulated data must be kept in a separate bucket owned by a compliance team that auditors can access independently.
- Test/staging environments: Replicate production data into a staging bucket in the same region with different permissions, without the cost of cross-region data transfer.
- Account separation: SRR works cross-account within the same region — useful for isolating production and DR accounts while keeping data local.
SRR replication does not incur data transfer costs because data stays within the same region. You only pay for the S3 PUT requests at the destination.
# SRR — enable versioning on both buckets in us-east-1
aws s3api put-bucket-versioning \
--bucket source-logs-bucket \
--versioning-configuration Status=Enabled
aws s3api put-bucket-versioning \
--bucket central-logs-bucket \
--versioning-configuration Status=Enabled
# Apply replication config (same JSON structure as CRR, just same-region ARNs)
aws s3api put-bucket-replication \
--bucket source-logs-bucket \
--replication-configuration file://srr-config.json
7. S3 Object Lock
S3 Object Lock implements Write Once Read Many (WORM) storage. Once enabled on a bucket, objects can be protected from deletion or overwrite for a fixed retention period — or indefinitely. Object Lock is essential for SEC 17a-4(f), CFTC, FINRA, and HIPAA compliance workloads.
7.1 Retention Modes
Governance Mode — Users with the s3:BypassGovernanceRetention IAM permission can delete or overwrite locked objects. Useful for internal compliance where you need an escape hatch for administrators.
Compliance Mode — No user, including the root account, can delete or overwrite a locked object before its retention period expires. The retention period itself cannot be shortened. Use this for regulatory mandates that require tamper-proof evidence.
7.2 Legal Hold
A legal hold is an on/off flag independent of the retention period. It prevents deletion regardless of any configured retention. Legal holds are used during litigation to preserve relevant objects indefinitely, then removed once the case is resolved.
7.3 Configuring Object Lock
# Create a new bucket with Object Lock enabled
aws s3api create-bucket \
--bucket compliance-archive-bucket \
--region us-east-1 \
--object-lock-enabled-for-bucket
# Set a default retention policy on the bucket (applied to all new objects)
aws s3api put-object-lock-configuration \
--bucket compliance-archive-bucket \
--object-lock-configuration '{
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Years": 7
}
}
}'
# Apply a retention override on a specific object version
aws s3api put-object-retention \
--bucket compliance-archive-bucket \
--key financial-records/2026-q1.csv \
--version-id abc123XYZ \
--retention '{
"Mode": "COMPLIANCE",
"RetainUntilDate": "2033-01-01T00:00:00Z"
}'
# Place a legal hold on an object
aws s3api put-object-legal-hold \
--bucket compliance-archive-bucket \
--key financial-records/2026-q1.csv \
--version-id abc123XYZ \
--legal-hold Status=ON
# Remove legal hold once litigation is resolved
aws s3api put-object-legal-hold \
--bucket compliance-archive-bucket \
--key financial-records/2026-q1.csv \
--version-id abc123XYZ \
--legal-hold Status=OFF
8. Cost Optimization Patterns
The previous sections covered individual features. Here is how to combine them into a coherent cost-optimization strategy for a real-world production bucket.
8.1 Tiered Lifecycle + Intelligent-Tiering Hybrid
For workloads where some data is accessed frequently and some is accessed unpredictably:
- Use standard S3 Standard for the first 24–48 hours (new data is always accessed during ingestion pipelines).
- Transition to INTELLIGENT_TIERING after 1 day for objects > 128 KB. Intelligent-Tiering handles the rest automatically.
- Use a separate lifecycle rule to delete temp/staging objects (prefix
tmp/) after 7 days. - Use
NoncurrentVersionExpirationwithNewerNoncurrentVersions: 3to keep only the 3 most recent versions.
8.2 Delete Incomplete Multipart Uploads
Incomplete multipart uploads accumulate silently and incur storage charges even though no complete object exists. The AbortIncompleteMultipartUpload lifecycle rule (shown in section 2.3) is the fix. This alone has saved companies thousands of dollars on large data pipeline buckets.
# Find incomplete multipart uploads in a bucket
aws s3api list-multipart-uploads \
--bucket my-production-bucket \
--query 'Uploads[*].{Key:Key,Initiated:Initiated,UploadId:UploadId}'
# Manually abort a specific incomplete upload
aws s3api abort-multipart-upload \
--bucket my-production-bucket \
--key large-file.tar.gz \
--upload-id "VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA"
8.3 S3 Inventory for Cost Analysis
Before tuning lifecycle rules, run S3 Inventory to understand your actual data distribution. Inventory produces daily or weekly CSV/ORC/Parquet reports with object size, storage class, last accessed date, replication status, and encryption status — perfect for feeding into Athena or a notebook for analysis.
# Enable S3 Inventory on a bucket (daily CSV report to a destination bucket)
aws s3api put-bucket-inventory-configuration \
--bucket my-production-bucket \
--id DailyCostInventory \
--inventory-configuration '{
"Id": "DailyCostInventory",
"IsEnabled": true,
"Destination": {
"S3BucketDestination": {
"Bucket": "arn:aws:s3:::my-inventory-reports-bucket",
"Format": "Parquet",
"Prefix": "inventory/my-production-bucket"
}
},
"Schedule": {
"Frequency": "Daily"
},
"IncludedObjectVersions": "All",
"OptionalFields": [
"Size",
"LastModifiedDate",
"StorageClass",
"ETag",
"ReplicationStatus",
"EncryptionStatus",
"IntelligentTieringAccessTier"
]
}'
8.4 Summary: Optimization Checklist
- Enable lifecycle rules with
AbortIncompleteMultipartUploadon every bucket - Add
NoncurrentVersionExpirationwithNewerNoncurrentVersionson all versioned buckets - Add
ExpiredObjectDeleteMarkerrule to remove stale delete markers - Filter lifecycle transitions with
ObjectSizeGreaterThan: 131072to avoid per-object IA overhead on small files - Use Intelligent-Tiering for datasets with unknown or changing access patterns
- Enable S3 Inventory and schedule monthly Athena queries to identify optimization opportunities
- Tag buckets and objects with
EnvironmentandCostCenterfor granular Cost Explorer breakdown - Enable CRR with RTC only where a 15-minute RPO SLA is actually required — SRR for compliance copies is cheaper