Guide · AWS ECR · Multi-Region Deployment

ECR Replication for MCP Servers — Cross-Region and Cross-Account Image Distribution

ECR replication automatically copies images pushed to a source registry to one or more destination registries — eliminating the need to push to multiple regions in CI and ensuring ECS tasks in every region pull from a local ECR endpoint. Three things catch teams early: replication is not retroactive — only images pushed after the replication configuration is applied are replicated; pre-existing images must be pushed again or copied manually; the replication configuration is a single object that replaces the entire existing configuration — adding a new destination region requires you to PUT the complete updated config, not just append a new rule; and cross-account replication requires a registry policy in the destination account granting the source account ecr:ReplicateImage — without it, replication silently fails with no error in the source account's CloudTrail.

TL;DR

Call put-replication-configuration with the complete rules array (one destination per region/account pair). For cross-account, also call put-registry-policy in the destination account. Replication applies to new pushes only — existing images are not backfilled. Check status with describe-image-replication-status. Add lifecycle policies in destination regions to cap storage. Budget $0.02/GB per replication transfer plus destination storage costs.

Replication configuration: cross-region

Replication is configured at the registry level (account + region) with a single put-replication-configuration call. The configuration applies to all repositories in the source registry, optionally filtered by repository name prefix.

## Configure cross-region replication: us-east-1 → eu-west-1 + ap-southeast-1
aws ecr put-replication-configuration \
  --replication-configuration '{
    "rules": [
      {
        "destinations": [
          { "region": "eu-west-1", "registryId": "123456789012" },
          { "region": "ap-southeast-1", "registryId": "123456789012" }
        ],
        "repositoryFilters": [
          {
            "filter": "mcp-server",
            "filterType": "PREFIX_MATCH"
          }
        ]
      }
    ]
  }'

## IMPORTANT: the above replaces the ENTIRE existing configuration.
## If you had an existing rule for eu-central-1 and only PUT the above,
## the eu-central-1 rule is removed.

## Verify current replication configuration
aws ecr describe-registry

Repository filters: the repositoryFilters array (optional) restricts which repositories are replicated. Filter type PREFIX_MATCH matches any repository whose name starts with the specified string. Omitting repositoryFilters replicates all repositories in the source registry. In most MCP deployments, filtering to mcp-server is preferable to replicating all repositories (which would include test, scratch, and tool images).

Cross-account replication

Cross-account replication copies images from one AWS account's registry to another account's registry. This is used in multi-account setups where images are built and stored in a centralized "tools" or "shared-services" account and deployed from regional production accounts.

## Step 1: In the SOURCE account (where images are built)
## Configure replication to a different account in eu-west-1
aws ecr put-replication-configuration \
  --replication-configuration '{
    "rules": [
      {
        "destinations": [
          {
            "region": "eu-west-1",
            "registryId": "999888777666"     // DESTINATION account ID
          }
        ],
        "repositoryFilters": [
          { "filter": "mcp-server", "filterType": "PREFIX_MATCH" }
        ]
      }
    ]
  }'

## Step 2: In the DESTINATION account (999888777666), create a registry policy
## granting the source account permission to replicate images
aws ecr put-registry-policy \
  --policy-text '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "AllowSourceAccountReplication",
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::123456789012:root"  // SOURCE account ID
        },
        "Action": [
          "ecr:CreateRepository",
          "ecr:ReplicateImage"
        ],
        "Resource": "arn:aws:ecr:eu-west-1:999888777666:repository/*"
      }
    ]
  }'

## Verify registry policy
aws ecr get-registry-policy

The ecr:CreateRepository permission in the registry policy is necessary because ECR creates the destination repository on first replication if it doesn't exist. Without it, replication fails when the image has never been replicated before.

Replication status and monitoring

Check whether a specific image has been replicated to destination regions using describe-image-replication-status. This is useful in CI pipelines to wait for replication before updating ECS task definitions in destination regions.

## Check replication status for a specific image
aws ecr describe-image-replication-status \
  --repository-name mcp-server \
  --image-id imageTag=v1.2.3

## Example output:
# {
#   "repositoryName": "mcp-server",
#   "imageId": { "imageTag": "v1.2.3", "imageDigest": "sha256:..." },
#   "replicationStatuses": [
#     {
#       "region": "eu-west-1",
#       "registryId": "123456789012",
#       "status": "COMPLETE",
#       "failureCode": null
#     },
#     {
#       "region": "ap-southeast-1",
#       "registryId": "123456789012",
#       "status": "IN_PROGRESS",
#       "failureCode": null
#     }
#   ]
# }
#!/usr/bin/env bash
# wait-for-replication.sh — wait until image is replicated to all regions
REPO=$1
TAG=$2
REGIONS=("eu-west-1" "ap-southeast-1")
MAX_WAIT=300

echo "Waiting for replication of $REPO:$TAG..."
ELAPSED=0
while [ "$ELAPSED" -lt "$MAX_WAIT" ]; do
  ALL_COMPLETE=true
  for REGION in "${REGIONS[@]}"; do
    STATUS=$(aws ecr describe-image-replication-status \
      --repository-name "$REPO" \
      --image-id imageTag="$TAG" \
      --query "replicationStatuses[?region=='$REGION'].status" \
      --output text)
    if [ "$STATUS" != "COMPLETE" ]; then
      ALL_COMPLETE=false
      echo "  $REGION: $STATUS"
    fi
  done

  if [ "$ALL_COMPLETE" = true ]; then
    echo "Replication complete in all regions."
    exit 0
  fi

  sleep 15
  ELAPSED=$((ELAPSED + 15))
done

echo "Replication timed out — proceeding with caution"
exit 1

Replication typically completes within 1–2 minutes for cross-region within the same account. Cross-account replication can take 2–5 minutes. EventBridge fires ECR Image Replication events when replication status changes — subscribe to receive async notification instead of polling.

CDK: replication configuration

// CDK: configure ECR cross-region replication via CfnRegistryPolicy and custom resource
// (No native L2 CDK construct for replication configuration as of CDK v2)
import * as cr from "aws-cdk-lib/custom-resources";

new cr.AwsCustomResource(this, "EcrReplication", {
  onCreate: {
    service: "ECR",
    action: "putReplicationConfiguration",
    parameters: {
      replicationConfiguration: {
        rules: [
          {
            destinations: [
              { region: "eu-west-1", registryId: this.account },
              { region: "ap-southeast-1", registryId: this.account },
            ],
            repositoryFilters: [
              { filter: "mcp-server", filterType: "PREFIX_MATCH" },
            ],
          },
        ],
      },
    },
    physicalResourceId: cr.PhysicalResourceId.of("EcrReplication"),
  },
  onUpdate: {
    service: "ECR",
    action: "putReplicationConfiguration",
    parameters: {
      replicationConfiguration: {
        rules: [
          {
            destinations: [
              { region: "eu-west-1", registryId: this.account },
              { region: "ap-southeast-1", registryId: this.account },
            ],
            repositoryFilters: [
              { filter: "mcp-server", filterType: "PREFIX_MATCH" },
            ],
          },
        ],
      },
    },
    physicalResourceId: cr.PhysicalResourceId.of("EcrReplication"),
  },
  policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
    resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
  }),
});

Cost model

Cost componentRateNotes
Data transfer for replication$0.02/GB per replicationCharged in the source region; same rate as standard inter-region data transfer for ECR
Destination ECR storage$0.10/GB-monthReplicated images stored in destination registry; add lifecycle policies in destination regions too
ECS task pull from same-region ECRFreeNo data transfer charge for ECS pulling from ECR in the same region

Cost example: a 500 MB MCP server image replicated to 3 destination regions: $0.02 × 0.5 GB × 3 destinations = $0.03 per release. For 2 releases per week over a month = $0.24/month transfer. Destination storage for 10 kept images × 500 MB × 3 regions = 15 GB × $0.10 = $1.50/month. Total: ~$1.74/month for 3-region replication — negligible compared to the ECS and data transfer costs of the deployment itself.

AliveMCP: multi-region probe worker replication

AliveMCP's probe workers run in three AWS regions to minimize round-trip latency to MCP endpoints in different geographies: us-east-1 (primary, where CI builds and pushes), eu-west-1 (European MCP endpoints), and ap-southeast-1 (Asia-Pacific MCP endpoints). ECR cross-region replication propagates each new probe worker image from us-east-1 to the two secondary regions within 2 minutes of push. The CI deployment pipeline calls wait-for-replication.sh before updating ECS task definitions in eu-west-1 and ap-southeast-1 — this prevents ECS from deploying with a task definition pointing to an image that hasn't arrived yet. Lifecycle policies are applied in all three regional ECR repos, keeping each to the last 10 images. The replication configuration uses a PREFIX_MATCH filter on mcp-server — dev, tooling, and migration images are not replicated.

Common failure modes

SymptomCauseFix
Replication status stays IN_PROGRESS indefinitely; never COMPLETEMissing registry policy in destination account for cross-account replication; or destination account doesn't allow ecr:ReplicateImageAdd registry policy to destination account with ecr:CreateRepository and ecr:ReplicateImage for the source account principal
Images in us-east-1 are not being replicated to eu-west-1 after adding new destinationAdded a new destination but the put-replication-configuration only included the new rule, dropping the existing rulesAlways PUT the complete replication configuration with all destinations — the call replaces the entire config
Pre-existing images are not in destination regionsReplication is not retroactive — only new pushes after configuration is applied are replicatedRe-tag and re-push existing images, or use aws ecr batch-get-image + ecr put-image to copy manifests programmatically
ECS task definition update in eu-west-1 fails: image not foundDeployment proceeded before replication completedWait for replication status COMPLETE before updating task definitions in secondary regions
Cross-account replication fails silently; no error in source CloudTrailDestination registry policy is missing or has incorrect account ID; failure is logged in destination account's CloudTrail, not sourceCheck CloudTrail in the destination account for ECR:ReplicateImage AccessDenied events
Storage grows in destination regions even with lifecycle policy in sourceLifecycle policies are per-repository per-region; a policy in us-east-1 does not apply to the replicated repo in eu-west-1Apply the same lifecycle policy to replicated repositories in each destination region