Skip to main content
emnode / learn
Site Reliability

Configure S3 Cross-Region Replication

A single bucket in a single Region is a single point of failure. Replicate critical data to a second Region — and understand the cost before you do.

13 min·10 sections·AWS

Last reviewed

S3 Cross-Region Replication: the basics

Why one Region isn't a disaster-recovery story

S3 gives you 99.999999999% (11 nines) durability inside a Region by spreading every object across multiple devices and Availability Zones. That protects you from disk failure and even from losing a whole AZ. It does not protect you from losing the Region — a rare but real event — and it does not give you a copy of your data anywhere a regional outage, a regulator, or a low-latency consumer in another geography can reach. Cross-Region Replication (CRR) is the feature that closes that gap by automatically and asynchronously copying objects to a bucket in a different AWS Region.

CRR is configured as one or more replication rules on a source bucket. A rule can cover the whole bucket or be scoped to a prefix or object tag, so you can replicate critical/ while leaving tmp/ behind. Every new PUT on the source is copied to the destination within seconds to minutes, including metadata, tags, and (optionally) delete markers. The hard prerequisite catches everyone the first time: versioning must be enabled on both the source and destination buckets, because replication tracks object versions, not just keys.

Continuity check COV-014 flags business-critical buckets that have no replication configured. It's a signal to decide, not an alarm — not every bucket needs a second Region. But for the buckets that hold data the business genuinely can't lose or can't afford to have stranded in a single Region during an outage, an unreplicated bucket is a disaster-recovery gap hiding behind a very reassuring durability number.

In this lesson you'll learn what Cross-Region Replication does and doesn't do, the hard prerequisite that versioning must be enabled on both source and destination, how to scope rules to a whole bucket or just a prefix, what replicates automatically and what needs S3 Batch Replication to back-fill, how delete markers and replica modification sync behave, the optional Replication Time Control (RTC) 15-minute SLA, and the full cost model — double storage, inter-Region transfer, replication requests, and RTC. You'll also see how CRR differs from Same-Region Replication and from AWS Backup, and the exact CLI calls to enable versioning, apply a replication configuration, and check replication status.

Fun fact

The replica that wasn't there yet

A team at a media company enabled Cross-Region Replication on a 40 TB asset bucket the morning after a near-miss regional event, breathed a sigh of relief, and moved on. Six weeks later they failed over to the replica during a planned DR test and found it held only 600 GB. The catch: CRR only replicates objects written after the rule is created — it does not back-fill the existing objects in the bucket. The other 39.4 TB needed a one-time S3 Batch Replication job to copy across. "Enabled replication" and "have a complete second copy" are two different states, and the gap between them is exactly the data you already had.

Configuring Cross-Region Replication in action

Lena runs the platform team at a logistics company. A continuity scan flags sevenc3-shipment-ledger — the bucket holding the immutable event log every downstream system replays from — as business-critical with no replication. It lives only in us-east-1. If that Region has a bad day, the entire reconciliation pipeline has nothing to replay from. Severity is medium, but the bucket's role makes it a clear yes.

She checks the prerequisites first. Replication tracks versions, so versioning has to be on for both the source bucket and the new destination bucket she's creating in us-west-2. She enables versioning on both, creates an IAM role that lets S3 read the source and write the destination, then applies a replication rule scoped to the whole bucket with Replication Time Control turned on so replicated objects land within the 15-minute SLA — important because the reconciliation job has its own timing assumptions.

One thing she doesn't skip: the back-fill. CRR only copies objects written after the rule exists, and the ledger has two years of history. She kicks off an S3 Batch Replication job to copy the existing objects across, then confirms with head-object that replication status reads COMPLETED on a sample of both old and new keys. The ongoing cost — roughly doubled storage plus inter-Region transfer on new events — goes onto the next cost review as a deliberate, owned line item.

Replication tracks object versions, so the hard prerequisite is versioning on BOTH buckets. Enable it on the source and the destination before anything else.

$ aws s3api put-bucket-versioning --bucket sevenc3-shipment-ledger --versioning-configuration Status=Enabled && aws s3api put-bucket-versioning --bucket sevenc3-shipment-ledger-dr --region us-west-2 --versioning-configuration Status=Enabled
# (no output on success — verify with get-bucket-versioning)
$ aws s3api get-bucket-versioning --bucket sevenc3-shipment-ledger
{
"Status": "Enabled"
}
$ aws s3api get-bucket-versioning --bucket sevenc3-shipment-ledger-dr --region us-west-2
{
"Status": "Enabled"
}
# Both versioned. Without this, put-bucket-replication fails with InvalidRequest.

Versioning on source AND destination is non-negotiable — replication is version-aware.

Now apply the replication configuration: an IAM role S3 can assume, the destination bucket ARN, whole-bucket scope, and Replication Time Control for the 15-minute SLA.

$ aws s3api put-bucket-replication --bucket sevenc3-shipment-ledger --replication-configuration '{"Role":"arn:aws:iam::123456789012:role/s3-crr-shipment-ledger","Rules":[{"ID":"replicate-all","Status":"Enabled","Priority":1,"Filter":{},"DeleteMarkerReplication":{"Status":"Enabled"},"Destination":{"Bucket":"arn:aws:s3:::sevenc3-shipment-ledger-dr","ReplicationTime":{"Status":"Enabled","Time":{"Minutes":15}},"Metrics":{"Status":"Enabled","EventThreshold":{"Minutes":15}}}}]}'
# (no output on success)
$ aws s3api head-object --bucket sevenc3-shipment-ledger --key events/2026/05/26/evt-9f2a.json --query ReplicationStatus
"PENDING"
# ...moments later...
"COMPLETED"
# New objects now replicate to us-west-2 within the 15-min RTC SLA. Existing objects still need Batch Replication.

Rule applied with RTC enabled — but only NEW writes replicate; back-fill the history separately.

Cross-Region Replication under the hooddeep dive

CRR is driven by a replication configuration attached to the source bucket and an IAM role S3 assumes to do the work. Because replication operates on object versions, both buckets must have versioning enabled — that's enforced, not advisory. When an object is written to the source, S3 asynchronously copies the version, its user metadata, ACL, tags, and (if you allow it) delete markers to the destination. The copy is eventually consistent and usually lands within seconds, but by default carries no SLA. The two things people get wrong are scope and back-fill: a rule with an empty Filter covers the whole bucket, a Filter with a prefix or tag scopes it, and in either case only objects written after the rule is created are replicated. Existing objects must be copied with a one-time S3 Batch Replication job — CRR never back-fills on its own.

Delete behavior is a deliberate choice. With DeleteMarkerReplication: Enabled, a delete on the source places a delete marker on the destination too, keeping the buckets in sync as a true mirror. With it disabled, deletes on the source do not propagate, so the destination retains objects the source has dropped — closer to a backup posture. Replica modification sync controls the reverse direction for bidirectional setups. By default, permanent version deletions (DeleteObjectVersion) are never replicated, which is intentional: it stops a deletion on one side from destroying the copy on the other. That single default is what keeps CRR from amplifying a malicious mass-deletion.

Replication Time Control (RTC) is the optional layer that converts CRR's best-effort timing into a contract: 99.99% of objects replicated within 15 minutes, backed by an SLA and CloudWatch replication metrics so you can alarm on lag. RTC costs extra per gigabyte on top of the normal transfer charge, so you enable it on the buckets whose downstream consumers have timing assumptions — not everywhere. It's worth being precise about what CRR is and isn't versus its neighbors: Same-Region Replication (SRR) is the identical mechanism with a destination in the same Region, used for log aggregation, account separation, or sovereignty within a Region rather than for regional DR. AWS Backup is a different tool entirely — it creates isolated, point-in-time recovery points in a separate vault you can lock against deletion. CRR gives you a live, continuously-updated copy for failover; Backup gives you a snapshot in time you can roll back to. They're complementary, and critical data often warrants both.

# Audit every bucket for a replication configuration and whether versioning (the prerequisite) is on.
for bucket in $(aws s3api list-buckets --query 'Buckets[].Name' --output text); do
  VER=$(aws s3api get-bucket-versioning --bucket "$bucket" --query 'Status' --output text 2>/dev/null)
  REPL=$(aws s3api get-bucket-replication --bucket "$bucket" \
           --query 'ReplicationConfiguration.Rules[0].Status' --output text 2>/dev/null || echo NONE)
  echo "$bucket  versioning=${VER:-Disabled}  replication=${REPL:-NONE}"
done

# Back-fill existing objects (CRR does NOT do this automatically) with an S3 Batch Replication job.
aws s3control create-job \
  --account-id 123456789012 \
  --operation '{"S3ReplicateObject":{}}' \
  --manifest-generator '{"S3JobManifestGenerator":{"SourceBucket":"arn:aws:s3:::sevenc3-shipment-ledger","EnableManifestOutput":false,"Filter":{"EligibleForReplication":true,"ObjectReplicationStatuses":["NONE","FAILED"]}}}' \
  --priority 10 --role-arn arn:aws:iam::123456789012:role/s3-crr-shipment-ledger --no-confirmation-required --region us-east-1

What is the impact of an unreplicated critical bucket?

The headline impact is regional single-point-of-failure. A full Region outage is rare, but when one happens, every bucket that lives only there is unreachable for the duration — and in the worst, very rare case of regional data loss, gone. For a bucket that downstream systems depend on, that's not a storage incident, it's a business-continuity incident: the recovery point objective (RPO) is "whatever you last copied out manually" and the recovery time objective (RTO) is "however long until the Region comes back," neither of which you control.

The second impact is compliance and data residency. Many regulatory regimes require either a recoverable second copy of regulated data or that data physically resides in a specific geography. An unreplicated bucket can fail an audit on the recovery requirement, and a bucket in the wrong Region with no replication path can fail a residency requirement. CRR addresses both — a second-Region copy for DR, or a same-region-family destination for sovereignty — but only if it was set up before the auditor asked.

The third impact is the cost of the protection itself, which is real and ongoing — this is the rare finding where doing the right thing raises the bill. You pay for storage in both Regions (roughly double the per-GB storage cost for replicated data), inter-Region data transfer on every byte replicated (a per-GB charge, plus a one-time charge to seed existing objects), a per-request charge for the replication operations, and an additional per-GB premium if RTC is enabled. A 1 TB critical bucket runs about $24/month in one Region and lands near $48/month replicated, plus transfer. That's why this is a per-data-class decision and not a blanket one — replicating ephemeral or regenerable data is pure waste.

The fourth impact is the gap between "enabled" and "complete." Teams enable replication, see the rule go green, and assume they have a full second copy — but CRR only replicates new writes. The existing objects, often the bulk of the data, sit unreplicated until someone runs an S3 Batch Replication job. A DR plan built on a half-populated replica is worse than no plan, because it fails exactly when you reach for it. Verifying replication status on both old and new objects is the step that turns a configuration into an actual recovery path.

How do you configure Cross-Region Replication properly?

Replication is a four-step loop: decide which buckets warrant it by data class, set the prerequisites and the rule, back-fill the existing data, then verify the recovery path actually works. Skip any step and you're either over-paying or holding a half-populated replica you'll only discover during a real failover.

1. Decide by data class — don't replicate everything

Tag each bucket with a data classification: regulated, business-critical, operational, ephemeral. Only the top two tiers usually justify a second Region — replicated storage costs roughly double, so replicating build artifacts or regenerable caches is pure waste. For each candidate, write down the RPO and RTO it actually needs; that's what decides whether you also need Replication Time Control's 15-minute SLA or whether best-effort timing is fine. The output of this step is a short, owned list, not a blanket policy.

2. Set the prerequisites, then the rule

Enable versioning on both the source and the destination bucket — replication is version-aware and won't apply without it. Create an IAM role that lets S3 read the source and write the destination (cross-account destinations need a bucket policy on the other side too). Then apply the replication configuration, scoped with an empty filter for the whole bucket or a prefix/tag filter for part of it. Choose delete behavior deliberately: enable delete-marker replication for a true mirror, disable it for a backup-leaning posture where the destination keeps what the source drops.

3. Back-fill existing objects with S3 Batch Replication

CRR only replicates objects written after the rule exists — it never back-fills automatically. For any bucket with existing data, run a one-time S3 Batch Replication job targeting objects whose replication status is NONE or FAILED. This is the step teams skip, and it's the one that turns "replication enabled" into "complete second copy." Expect a one-time inter-Region transfer charge proportional to the existing data size; it hits once and then tapers to the steady-state rate.

4. Verify the recovery path, not just the configuration

A replica you've never failed over to is a hypothesis, not a recovery path. Check ReplicationStatus on a sample of both old and new objects with head-object — it should read COMPLETED, not PENDING or FAILED. Then periodically do a real read from the destination Region to prove IAM, KMS key access, and bucket policy on the destination all line up. Wire CloudWatch replication metrics (and, with RTC, the replication-latency alarm) so you find out about a stalled rule before an outage does.

# Confirm replication is actually completing on a sample of objects (new AND back-filled).
for key in events/2026/05/26/evt-9f2a.json archive/2024/01/02/evt-0001.json; do
  STATUS=$(aws s3api head-object --bucket sevenc3-shipment-ledger --key "$key" \
             --query ReplicationStatus --output text)
  echo "$key  ->  $STATUS"
done

# Prove the recovery path: read the replica directly from the destination Region.
aws s3api head-object --bucket sevenc3-shipment-ledger-dr --region us-west-2 \
  --key events/2026/05/26/evt-9f2a.json --query '{Size:ContentLength,Modified:LastModified}'

Quick quiz

Question 1 of 5

You enable Cross-Region Replication on a critical 8 TB bucket that's been in production for two years. The rule shows Enabled and new objects show ReplicationStatus COMPLETED. Is your disaster-recovery copy ready?

You've completed Configure S3 Cross-Region Replication. You now know why 11-nines durability isn't a regional-DR story, the hard prerequisite that versioning must be on for both buckets, how to scope rules and choose delete-marker behavior, why CRR never back-fills existing objects on its own, what RTC's 15-minute SLA buys, the full double-storage-plus-transfer cost model, and how CRR differs from SRR and from AWS Backup. The next time a continuity scan flags a critical bucket with no replication, you'll have a four-step loop — decide, configure, back-fill, verify — and you'll know to check both old and new objects before calling the recovery path real.

Back to the library