S3 buckets should have cross-region replication enabled
A single-region S3 bucket is a single point of failure for data availability. Regional outages, while rare, do happen. Cross-region replication copies new object versions to a bucket in a separate region, giving you a warm standby that supports recovery time objectives measured in minutes rather than hours.
CRR can support regulatory expectations for geographically separated backups. Without it, restoring data after a regional event depends on backup and recovery mechanisms you may or may not have configured.
Retrofit consideration
Enabling CRR on existing buckets requires versioning on both source and destination buckets. If versioning was not previously enabled, you need to account for noncurrent object versions and the resulting storage cost increase. CRR only replicates objects written after the rule is created; existing objects require a separate S3 Batch Replication job.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "s3_bucket" {
source = "soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "pcidss.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "hipaa.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nist80053.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nistcsf.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "fedrampmoderate.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "cisv80ig1.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nist800171.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "cisacyberessentials.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nydfs23.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "ffiec.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "eugmpannex11.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "cfrpart11.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "rbicybersecurity.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "rbiitfnbfc.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "fedramplow.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "hipaasecurity2003.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nistcsfv11.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nist80053rev4.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "pcidssv321.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
If you use terraform-aws-modules/s3-bucket/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
replication_configuration = {
rules[0] = {
status = "Enabled"
}
}
}
Use AWS provider resources directly. See docs for the resources involved: aws_s3_bucket_replication_configuration.
resource "aws_s3_bucket" "this" {
bucket = "pofix-abc123"
force_destroy = true
}
resource "aws_s3_bucket_replication_configuration" "this" {
bucket = "example-bucket-abc123"
role = "arn:aws:iam::123456789012:role/example-role"
rule {
delete_marker_replication {
status = "Enabled"
}
destination {
bucket = "arn:aws:s3:::example-bucket-abc123"
storage_class = "STANDARD"
}
filter {
}
id = "cross-region-replication"
priority = 10
status = "Enabled"
}
}
What this control checks
The policy checks that an aws_s3_bucket_replication_configuration resource is associated with each S3 bucket and that at least one replication rule is active.
To pass, three things must be in place. First, versioning must be enabled on both source and destination buckets via aws_s3_bucket_versioning with versioning_configuration { status = "Enabled" }. Second, an aws_iam_role must exist with a trust policy allowing s3.amazonaws.com to assume it and an attached policy granting s3:GetReplicationConfiguration, s3:ListBucket, s3:GetObjectVersionForReplication, s3:GetObjectVersionAcl, s3:GetObjectVersionTagging on the source and s3:ReplicateObject, s3:ReplicateDelete, s3:ReplicateTags on the destination. Third, the aws_s3_bucket_replication_configuration resource must reference the source bucket via bucket, the IAM role via role, and include at least one rule block with status = "Enabled" and a destination block pointing to a bucket ARN in a different region. A filter block (even if empty) is required in current provider versions. Buckets with no replication configuration, or with all rules set to status = "Disabled", fail.
Common pitfalls
Versioning must be enabled on both buckets
CRR requires
aws_s3_bucket_versioningwithversioning_configuration { status = "Enabled" }on both source and destination. If either bucket has versioning suspended or not configured, thePutBucketReplicationAPI call fails withInvalidRequest. This is a common deployment blocker when retrofitting existing buckets.Existing objects are not replicated automatically
Objects that existed before the replication rule was created are not copied. They stay source-only until you run an S3 Batch Replication job via
aws_s3control_jobor the console. Auditors may flag gaps if they compare object counts between source and destination and find the numbers don't line up.Deprecated inline replication_configuration block
Use the standalone
aws_s3_bucket_replication_configurationresource. The inlinereplication_configurationblock insideaws_s3_bucketwas removed in provider v4, and mixing old patterns with the standalone resource causes state drift and unexpected plan diffs.Delete marker replication must be configured when needed
With V2 replication rules, delete markers are not replicated unless you explicitly set
delete_marker_replication { status = "Enabled" }. Skip it and deleting an object in the source leaves the replica intact, which breaks consistency assumptions during DR testing.Cross-account replication requires destination bucket policy
When replicating to a bucket in a different AWS account, the destination bucket policy must explicitly grant
s3:ReplicateObject,s3:ReplicateDelete, ands3:ObjectOwnerOverrideToBucketOwnerto the source account's replication role ARN. Missing this policy causes replication failures that are typically diagnosed through S3 replication metrics and status.
Audit evidence
An auditor expects Config rule evaluation results showing s3-bucket-replication-enabled as COMPLIANT for every in-scope bucket. Supporting evidence includes the S3 console Replication tab showing active rules with a destination bucket in a different region, and replication metrics confirming objects are being replicated successfully. CloudTrail logs for PutBucketReplication calls show when CRR was configured and by whom.
For ongoing assurance, Config conformance pack reports or Security Hub findings exported to a compliance dashboard give continuous coverage. If S3 Batch Replication was used to backfill existing objects, retain the Batch Operations job completion report as well.
Framework-specific interpretation
SOC 2: The A-series Availability criteria require backup and recovery capabilities. Geographic redundancy for S3-hosted data via CRR strengthens the evidence auditors look for under those criteria.
PCI DSS v4.0: Requirement 12.10 covers incident response planning, and CRR can support resilience objectives there. It does not satisfy core PCI DSS data protection controls on its own.
HIPAA Omnibus Rule 2013: The Security Rule at 45 CFR 164.308(a)(7) covers contingency planning, including data backup and disaster recovery. CRR can provide a continuously updated copy of ePHI in S3, supporting lower recovery point objectives when a regional failure occurs.
NIST SP 800-53 Rev 5: Addresses CP-9 by keeping backup copies at a separate geographic location and supports CP-6 (Alternate Storage Site) by placing replicas in a different region. Both controls are in scope for any NIST 800-53 system using S3 for data storage.
NIST Cybersecurity Framework v2.0: S3 cross-region replication feeds into CSF 2.0 Recover (RC) objectives, specifically recovery planning and data resilience. The Protect (PR) outcomes around data management are also supported by maintaining geographically separated copies.
FedRAMP Moderate Baseline Rev 4: CP-9 and CP-10 both call for backup copies at geographically separated facilities. CRR can satisfy that requirement for objects stored in S3 by maintaining a live replica in a second region.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
s3_bucket_cross_region_replication_enabledAWS Config Managed Rule:
S3_BUCKET_CROSS_REGION_REPLICATION_ENABLEDCheckov Check:
CKV_AWS_144Powerpipe Control:
aws_compliance.control.s3_bucket_cross_region_replication_enabledProwler Check:
s3_bucket_cross_region_replicationAWS Security Hub Control:
S3.7
Last reviewed: 2026-03-09