I set up S3 Cross-Region Replication to backup data from a bucket in us-east-1 to a bucket in eu-west-1. The replication rule looked correct, but days later, objects in the destination bucket were missing. I checked the replication status and saw “PENDING” and “FAILED” states, which sent me down a rabbit hole of IAM roles, versioning settings, and replication rule filters. In this post, I’ll walk through exactly what causes this and how to fix it.
The Problem
You’ve configured S3 Cross-Region Replication (CRR) but new objects uploaded to the source bucket don’t appear in the destination. In the S3 console, the replication status shows PENDING or FAILED, or objects simply don’t appear with no status recorded.
| Error Type | Description |
|---|---|
| Replication Status: PENDING | The object is queued for replication but hasn’t been replicated yet. |
| Replication Status: FAILED | Replication attempted but failed, usually due to permissions or configuration. |
| No Status | Object exists in source but no replication status appears (configuration issue). |
Why Does This Happen?
- Replication only applies to new objects — CRR is prospective, not retroactive. Objects uploaded before CRR was enabled are not replicated. Existing objects must be replicated manually using S3 Batch Operations.
- IAM role lacks permissions — The replication role must have
s3:GetObjecton the source bucket ands3:PutObjecton the destination. Without both, replication fails silently. - Destination bucket versioning not enabled — S3 CRR requires versioning on both the source and destination buckets. If the destination lacks versioning, replication fails.
- Source bucket versioning not enabled — CRR cannot function without versioning on the source bucket. The replication configuration itself requires the source to be versioned.
- Replication rule filter excludes the object — The replication rule uses a prefix or tag filter that doesn’t match your objects. Objects outside the filter scope are silently ignored.
The Fix
Step 1: Enable Versioning on Both Buckets
Both the source and destination buckets must have versioning enabled:
# Enable versioning on source bucket
aws s3api put-bucket-versioning \
--bucket source-bucket \
--versioning-configuration Status=Enabled
# Enable versioning on destination bucket
aws s3api put-bucket-versioning \
--bucket destination-bucket \
--versioning-configuration Status=Enabled
# Verify versioning is enabled
aws s3api get-bucket-versioning --bucket source-bucket
Step 2: Create or Update the IAM Role
Create an IAM role with the required permissions:
cat > trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
aws iam create-role \
--role-name s3-replication-role \
--assume-role-policy-document file://trust-policy.json
cat > role-policy.json <<EOF
{
"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"
],
"Resource": "arn:aws:s3:::source-bucket/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete"
],
"Resource": "arn:aws:s3:::destination-bucket/*"
}
]
}
EOF
aws iam put-role-policy \
--role-name s3-replication-role \
--policy-name s3-replication-policy \
--policy-document file://role-policy.json
Step 3: Configure Replication Rule
Create the replication configuration:
cat > replication-config.json <<EOF
{
"Role": "arn:aws:iam::123456789012:role/s3-replication-role",
"Rules": [
{
"ID": "replicate-all",
"Status": "Enabled",
"Priority": 1,
"Filter": {
"Prefix": ""
},
"Destination": {
"Bucket": "arn:aws:s3:::destination-bucket",
"ReplicationTime": {
"Status": "Enabled",
"Time": {
"Minutes": 15
}
}
}
}
]
}
EOF
aws s3api put-bucket-replication \
--bucket source-bucket \
--replication-configuration file://replication-config.json
Step 4: Verify Replication Configuration
Check the replication rule is applied:
aws s3api get-bucket-replication --bucket source-bucket
Step 5: Replicate Existing Objects (Optional)
If you need to replicate objects uploaded before CRR was enabled:
# List objects and their replication status
aws s3api head-object \
--bucket source-bucket \
--key your-object-key
# Use S3 Batch Operations to replicate all existing objects
# This requires creating a Batch Operations job through the console or SDK
How to Run This
- Replace
source-bucketanddestination-bucketwith your actual bucket names - Replace
123456789012with your AWS account ID - Run commands in order: enable versioning first, then create the IAM role, then apply the replication configuration
- Upload a test object to the source bucket and check the destination within 15 minutes
- Verify replication status in the S3 console or using
head-object
Is This Safe?
Replication is safe and recommended for disaster recovery. The IAM role is scoped to the source and destination buckets, preventing access to other resources. For production, use Replication Time Control (RTC) to guarantee 15-minute replication with compliance reports.
Key Takeaway
S3 Cross-Region Replication requires versioning on both buckets, a properly configured IAM role, and a matching replication rule filter. Test with a new object immediately after setup to confirm the configuration works.
Have questions or ran into a different S3 issue? Connect with me on LinkedIn or X.