๐ DynamoDB Migration Project
January 14, 2026 ยท View on GitHub
This sample development project presents the content explained in the DynamoDB migration playbook. โ ๏ธ This project is not intended to be deployed in production as-is, and it is your responsibility to complete and run proper testing in lower environments. โ ๏ธ
๐ Getting Started
To execute this CDK project, you'll need to provide the sourceTableArn and the destinationTableArn DynamoDB table ARNs. For the source table you must enable DynamoDB Streams to project NEW_AND_OLD_IMAGES view type for this solution to work properly.
๐ Before you begin, ensure your shell has credentials for the account you're operating in through your AWS profile or your environment variables.
Copy and paste your table ARNs into the shell variables while setting the correct AWS region to deploy the resources:
# Change to match your region. This should be the same region as the source table.
export AWS_DEFAULT_REGION=us-east-1
# The source table should be in the same account as the deployed resources.
export SOURCE_TABLE_ARN=arn:aws:dynamodb:us-east-1:111122223333:table/my-source-table
# If destination table is in a different account, follow the 'Cross-account access' section
export DEST_TABLE_ARN=arn:aws:dynamodb:us-east-1:111122223333:table/my-source-table-migrated
๐ Setup for macOS (for brand new users)
If this is your first time running any CDK application and you happen to be on macOS, follow these instructions first to install dependencies.
Prerequisites:
- You should have brew installed.
- You should set
AWS_DEFAULT_REGIONto the region you want to operate in.
Install the following packages with brew to begin:
brew install typescript
brew install aws-cdk
brew install node
With npm, Install the aws-cdk-lib to start:
npm i aws-cdk-lib
Then you need to bootstrap CDK:
cdk bootstrap -c sourceTableArn=$SOURCE_TABLE_ARN -c destinationTableArn=$DEST_TABLE_ARN
๐ Deployment
The following command will generate the synthesized CloudFormation template, you can use this output to explore the stack that will be generated.
cdk synth -c sourceTableArn=$SOURCE_TABLE_ARN -c destinationTableArn=$DEST_TABLE_ARN
Once you are ready to deploy your solution you can execute it with the following command. Please remember the source table needs to have Amazon DynamoDB streams enabled.
cdk deploy -c sourceTableArn=$SOURCE_TABLE_ARN -c destinationTableArn=$DEST_TABLE_ARN
...
...
DdbMigration-source-table-To-destination-table | 33/33 | 11:45:37 AM | CREATE_COMPLETE | AWS::CloudFormation::Stack | DdbMigration-source-table-To-destination-table
โ
DdbMigration-source-table-To-destination-table
โจ Deployment time: 81.71s
Outputs:
DdbMigration-source-table-To-destination-table.DestinationTablePolicy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:BatchWriteItem",
"dynamodb:DescribeTable"
],
"Principal": {
"AWS": [
"arn:aws:iam::1111222223333:role/DdbMigration-source-table-To-de-GlueJobRoleF1B69418-DiAybmqsORAy",
"arn:aws:iam::1111222223333:role/DdbMigration-source-table-WriteCdcLambdaServiceRole-Zl7IcNJaFqsM"
]
},
"Resource": "arn:aws:dynamodb:us-east-1:1111222223333:table/destination-table"
}
]
}
DdbMigration-source-table-To-destination-table.DirectMigrationJobName = DirectMigrationJob-l63F97BtqXQq
DdbMigration-source-table-To-destination-table.LargeMigrationJobName = LargeMigrationJob-VSYJGsC9ISBz
DdbMigration-source-table-To-destination-table.MigrationBucketName = ddbmigration-source-table--migrationbucket1234567
DdbMigration-source-table-To-destination-table.StateMachineArn = arn:aws:states:us-east-1:1111222223333:stateMachine:DdbMigration-source-table-To-destination-table
Stack ARN:
arn:aws:cloudformation:us-east-1:1111222223333:stack/DdbMigration-source-table-To-destination-table/eeab6590-eaf2-1111-a0a0-0affea56b8cb
โจ Total time: 86.88s
- Run the
cdk deploycommand and note the output of the IAM policy in the Output DestinationTablePolicy. - Copy the IAM policy into your clipboard. This is a resource-based policy that must be applied to the destination DynamoDB table in your destination account. If you do not see this output, the script has determined the source and destination are the same AWS account. You can also see this output on the CloudFormation stack in the AWS Management Console.
- Follow these developer documentation instructions to add the policy to your destination table, preferably using the AWS Management Console.
- Execute the code in AWS Step Functions console as normal. The Lambda function WriteCdc will write cross-account into your table with the permissions granted by this resource-based policy
๐ Cross-account access
The resources for the migration as well as the source DynamoDB table must be in the same account, but the destination table can be in any account. However, you must update the destination table's permissions with a resource-based policy created and placed into the CloudFormation stack Outputs section in order for the replication to work.
๐ Note: If you attempt to deploy this into an AWS account different from the source table's account, the CloudFormation stack creation will fail with an error due to a custom resource we made to validate account ids called AccountValidationCustomResource. If you make this mistake, you must run the clean-up step to destroy the stack.
๐งน Clean-up
To destroy the resources (when the migration is completed and you decide to cut-over), execute:
cdk destroy -c sourceTableArn=$SOURCE_TABLE_ARN -c destinationTableArn=$DEST_TABLE_ARN
โ ๏ธ Current Limitations
- The current deployment assumes the deployed resources and the source table are in the same account. The destination table can be in a separate account.
- You must change the table ARNs and re-run
cdk deployfor every table combination. You can't re-use the same stack for different table combinations.
๐ Acknowledgements
We would like to extend our heartfelt thanks to the major collaborators who made significant contributions to this project:
- ๐ Esteban Serna
- ๐ Sean Shriver
- ๐ John Terhune
Their expertise, dedication, and hard work have been instrumental in the development and success of this DynamoDB Migration Project. We are truly grateful for their valuable input and collaborative spirit.
๐ค Contributing
We welcome contributions from the community! Whether you're fixing bugs, improving documentation, or proposing new features, your efforts are greatly appreciated. Here are some ways you can contribute:
๐ Feature Enhancements
- Help us increase the current throughput limitation of 9K TPS
- Implement new migration strategies or optimizations
- Add support for additional AWS services or integrations
๐งช Testing
- Improve and expand our unit test coverage
- Develop integration tests
- Perform thorough testing in various scenarios and environments
๐ Documentation
- Improve existing documentation for clarity and completeness
- Add examples, tutorials, or use cases
- Translate documentation to other languages
๐งน Code Quality
- Implement or improve linting configurations
- Refactor code for better readability and maintainability
- Optimize performance in existing codebase
๐ Bug Hunting
- Identify and report bugs
- Provide detailed reproduction steps for issues
- Submit pull requests with bug fixes
๐ก Ideas and Discussions
- Propose new features or improvements
- Participate in discussions about the project's direction
- Share your use cases and how the project could better support them
To get started:
- Please create an issue first to discuss your contribution.
- Fork the repository
- Create a new branch for your contribution
- Make your changes
- Submit a pull request with a clear description of your changes
Please ensure your code adheres to our coding standards and includes appropriate tests and documentation.
We look forward to your contributions and are excited to see how together we can improve this DynamoDB Migration Project!
๐ Original Readme - Useful commands
npm run buildcompile typescript to jsnpm run watchwatch for changes and compilenpm run testperform the jest unit testsnpx cdk deploydeploy this stack to your default AWS account/regionnpx cdk diffcompare deployed stack with current statenpx cdk synthemits the synthesized CloudFormation template