A
Arun's Blog
All Posts

Migrating DynamoDB Tables Across AWS Accounts via S3

|4 min read|
DynamoDBMigrationDatabase
TL;DR

Migrate DynamoDB tables across AWS accounts using S3 as an intermediary. Export from source account using export-table-to-point-in-time, create an S3 bucket in the destination with cross-account access, then import using import-table with a table creation parameters file.

Introduction

DynamoDB doesn't have a one-shot cross-account move command. To migrate a table from one AWS account to another, the cleanest path is to export the source table to an S3 bucket that both accounts can reach, then import from that S3 path on the destination side.

This post walks through the full sequence: bucket setup with cross-account policy, export-to-S3 from the source, and import-table on the destination. It works well for one-time migrations or periodic data transfers.

Note

This post explains how to migrate DynamoDB tables to another AWS account using the export/import method via S3. This approach works well for one-time migrations or periodic data transfers.

Prerequisites

  • Access to both source and destination AWS accounts
  • Permissions to:
    • Create an S3 bucket in the target AWS account
    • Backup the source DynamoDB table
    • Create and restore DynamoDB tables in the target account
    • Access AWS CLI or CloudShell

Logical Architecture

DynamoDB Migration Architecture

Steps

Destination Account - Create S3 Bucket

Create S3 Bucket for Backup

# Set the variable for the bucket name
BUCKET_NAME="dynamodb-backup"

# Create the bucket
aws s3api create-bucket --bucket $BUCKET_NAME --region us-east-1

Create Bucket Policy for Cross-Account Access

The bucket policy needs a single Allow statement that lists both account root ARNs as Principals (source and destination), and the Resource as both the bucket ARN and the bucket-ARN/*. Apply it with aws s3api put-bucket-policy. In production, lock the Action down to s3:PutObject, s3:GetObject, and s3:ListBucket rather than s3:*.

Important

Replace SOURCE_ACCOUNT_ID and DESTINATION_ACCOUNT_ID with your actual AWS account IDs. Using s3:* is permissive - consider restricting to only the actions needed (s3:PutObject, s3:GetObject, s3:ListBucket).

Source Account - Backup DynamoDB

# Export DynamoDB table to S3 bucket in destination account
aws dynamodb export-table-to-point-in-time \
  --region us-east-1 \
  --table-arn arn:aws:dynamodb:us-east-1:SOURCE_ACCOUNT_ID:table/tblARUN \
  --s3-bucket dynamodb-backup \
  --s3-bucket-owner DESTINATION_ACCOUNT_ID

Check the export status:

aws dynamodb describe-export --export-arn [ARN from backup command]
Pro Tip

The backup creates subfolders in S3 at AWSDynamoDB/[random-guid]/data. Note this path - you'll need it for the restore command.

Wait until status shows 'Completed' before proceeding to restore.

Destination Account - Restore DynamoDB

Create Table Parameters File

Create a file called dbparameters.json:

The parameters file is the same shape you'd pass to CreateTable: TableName, AttributeDefinitions (name + type for each attribute used in the schema), KeySchema (HASH for partition key, RANGE for sort key), and either BillingMode: PAY_PER_REQUEST or PROVISIONED with ProvisionedThroughput. The attribute names and types must match what's actually in the exported data, otherwise the import fails with a schema mismatch.

Import Table from S3

aws dynamodb import-table \
  --s3-bucket-source S3Bucket=dynamodb-backup,S3KeyPrefix=AWSDynamoDB/[random-guid]/data \
  --input-format DYNAMODB_JSON \
  --table-creation-parameters file://dbparameters.json \
  --input-compression-type GZIP

Check Restore Status

aws dynamodb describe-table --table-name tblDANIEL

Troubleshooting

  • Export fails with AccessDenied - Verify the S3 bucket policy allows the source account. Check that your IAM role has dynamodb:ExportTableToPointInTime permission.
  • Import fails with "table already exists" - Delete the existing table first or use a different table name in dbparameters.json.
  • Import fails with schema mismatch - Ensure the KeySchema in dbparameters.json matches the source table's key structure exactly (same attribute names and types).
  • Cannot find export path in S3 - The export creates nested folders. Navigate through AWSDynamoDB/ to find the GUID folder containing your export data.
  • Export stuck in IN_PROGRESS - Large tables take time. Check CloudWatch for errors. Ensure the source table has Point-in-Time Recovery enabled.
  • Permission denied on bucket - Verify the bucket policy includes both account IDs. Check that the IAM user/role has S3 permissions.

Want Help With This?

If you're working on something similar and want a second set of eyes, or you'd like to talk through how this applies to your environment, reach out via the contact form. Happy to help.

Related Articles