MENU
Deployment and Migration
Deployment and migration are two related but distinct concerns when managing databases on AWS. Deployment is the process of setting up and configuring a database in AWS — creating an instance, choosing an instance type and storage option, and configuring security — using a service such as Amazon RDS, Amazon Aurora, or Amazon DocumentDB. Migration is the process of moving data from one database to another, whether from an on-premises database into AWS or between two AWS databases, using tools such as AWS Database Migration Service (DMS) and AWS Schema Conversion Tool (SCT). SCT and DMS also support conversion between different database types — for example, SCT can convert a MongoDB schema to a MySQL schema, and DMS can then migrate the data from MongoDB to MySQL.Deployment Automation
Automating database deployments reduces the time and error risk associated with manual setup, and makes deployments consistent and repeatable across environments.Infrastructure as Code
Infrastructure as Code (IaC) tools such as AWS CloudFormation and Terraform define the desired state of infrastructure in code, which can be version-controlled, tested, and deployed automatically. A CloudFormation template can declare a VPC, subnet, security group, and an RDS DB instance together, then be deployed with:| aws cloudformation create-stack --stack-name mydatabase --template-body file://database.yaml |
Creates a CloudFormation stack from a local template file, provisioning every resource it declares.
The same infrastructure can be declared equivalently with Terraform and deployed with terraform init followed by terraform apply. Both approaches are shown in full in the code examples below.
CI/CD
Integrating database deployments into a Continuous Integration/Continuous Delivery (CI/CD) pipeline — using tools such as AWS CodePipeline and AWS CodeBuild — ensures database changes are tested and validated before reaching production.Preconfigured Solutions and Monitoring
Amazon RDS offers preconfigured, scalable, secure, and highly available solutions for popular engines (MySQL, PostgreSQL, Oracle, and others) that can be deployed in a few clicks from the console or the AWS CLI. Once deployed, Amazon CloudWatch monitors key database metrics and can raise alerts on conditions such as high CPU usage or low disk space.Evaluating Application Requirements
Before automating a deployment, evaluate the application's requirements to determine which components to deploy:- Data model — a relational data model favors an engine such as MySQL or PostgreSQL; a NoSQL data model favors DynamoDB or DocumentDB. See Database Types for the full range of AWS database categories.
- Scale — applications needing high scalability and availability favor a managed service such as RDS or Aurora, which scale automatically and provide replication and failover.
- Performance — workloads needing high throughput and low latency may call for an in-memory engine such as Amazon ElastiCache.
- Security — sensitive data may require an engine with built-in encryption, such as RDS with encryption at rest.
- Cost — managed services such as RDS and Aurora typically cost more than self-managed engines running on EC2.
Choosing Deployment Tools
When selecting deployment tools and services, consider the team's existing familiarity with a tool; the complexity of the deployment (the console or CLI for simple deployments, CloudFormation or Terraform for deployments spanning multiple resources); how well the tool integrates with an existing CI/CD pipeline such as Jenkins or GitLab; the level of vendor support and documentation available; and any cost the tool adds beyond standard AWS fees.Data Preparation and Migration
Preparing for a migration involves identifying every data source to migrate (on-premises databases, third-party applications, cloud services), determining the data's type and format (structured, unstructured, or semi-structured such as JSON/XML), assessing data quality (missing data, duplicates, inconsistencies), choosing a migration method appropriate to the data volume and downtime tolerance, planning the migration sequence and rollback procedure, and monitoring and tuning database performance during and after the migration.Data Migration Methods
Snapshots, replication, and restore are the three broad migration methods; the right choice depends on data size, data complexity, tolerable downtime, and the desired level of control:- Larger datasets favor replication or restore; smaller datasets are often well suited to snapshots.
- Strict uptime requirements favor methods requiring less downtime, such as replication.
- Highly structured data that must be preserved during migration favors replication; unstructured, easily recreated data can use snapshots.
- Snapshots require minimal configuration; replication requires more careful setup but offers finer control over the migration process.
- Some methods suit relational databases better; others suit NoSQL databases better.
Migration Tools and Services
AWS Database Migration Service (DMS), AWS Schema Conversion Tool (SCT), and native database tools (MySQL Workbench's Migration Wizard, SQL Server Management Studio's Import and Export Wizard) are the principal migration tools on AWS. Choosing among them depends on the migration's complexity, the source and target database types, the data-consistency guarantees required, the tolerable downtime, cost, and ease of use.| AWS DMS | A fully managed service supporting homogeneous migrations (e.g. Oracle to Oracle) and heterogeneous migrations (e.g. Oracle to PostgreSQL), with setup, configuration, and ongoing monitoring built in. |
| AWS SCT | Converts the schema and code of a relational database — Oracle, Microsoft SQL Server, or MySQL — to run on Aurora, PostgreSQL, MySQL, or MariaDB. SCT can be used standalone (without DMS) to generate the SQL scripts that create the target schema, leaving data migration to other tools. |
| Native tools | Tools bundled with the database software, such as MySQL Workbench or SQL Server Management Studio, suit smaller or simpler migrations. |
AWS Database Migration Service (DMS)
AWS DMS is a managed migration and replication service that moves databases and analytics workloads into AWS while the source database remains fully operational, minimizing application downtime. It supports homogeneous migrations (Oracle to Oracle) as well as heterogeneous migrations between engines (Oracle or SQL Server to Aurora), and can continuously replicate data with low latency from a supported source to a supported target — for example, streaming multiple sources into Amazon S3 to build a data lake, or into Amazon Redshift to build a data warehouse.Most replication tasks can be set up in under 10 minutes from the DMS section of the console: specify source and target endpoints, choose or create a replication instance, and accept or customize the schema mapping rules. Billing covers only the replication instances used and any additional log storage; data transfer itself is free, and DMS Schema Conversion is free to use as part of DMS (only storage is billed).
A typical migration creates the target database, migrates the schema, sets up data replication, performs a full load followed by ongoing change data capture and apply, and finishes with a switchover of the production environment once the target has caught up with the source. For continuous data replication rather than a one-time cutover, the same process applies but omits the final switchover step — the task simply runs until stopped or changed. Compare this asynchronous, continuous replication model with MySQL's own Replication mechanisms.
DMS can read from and write to encrypted databases: it connects at the SQL interface layer, so it can extract decrypted data from sources using Transparent Data Encryption (Oracle, SQL Server) or storage-level encryption, and propagate it to the target. Data encrypted at the application level passes through DMS unchanged, still encrypted, and is inserted into the target as-is; enabling encryption-at-rest on the target is recommended to preserve confidentiality.
Migration progress can be monitored through DMS metrics in the console, which give an end-to-end view of the replication pipeline including diagnostic and performance data at each stage. DMS also integrates with AWS CloudTrail and CloudWatch Logs, and exposes a provisioning API and CLI so that replication tasks can be created, restarted, managed, and terminated programmatically or on a schedule from outside the console.
Supported DMS Sources and Targets
Either the source or the target (or both) must reside in RDS or on EC2; replication directly between two on-premises databases is not supported.- On-premises / EC2 sources — Oracle; SQL Server (Enterprise, Standard, Workgroup, Developer — not Web or Express); MySQL; MariaDB (as a MySQL-compatible source); PostgreSQL; MongoDB; SAP ASE; IBM Db2 for Linux, UNIX, and Windows; plus Azure SQL Database and Google Cloud for MySQL.
- RDS / S3 sources — Oracle; SQL Server (same edition restrictions); MySQL; MariaDB; PostgreSQL; Aurora MySQL-Compatible and Aurora PostgreSQL-Compatible; Amazon S3; Amazon DocumentDB (with MongoDB compatibility).
- On-premises / EC2 targets — Oracle (all editions except Express); MySQL; MariaDB; PostgreSQL; SAP ASE; Redis.
- RDS and other AWS targets — Oracle, SQL Server, MySQL, MariaDB, PostgreSQL, Aurora MySQL-Compatible, Aurora PostgreSQL-Compatible, Aurora Serverless v2, Amazon Redshift, Amazon S3, Amazon DynamoDB, Amazon OpenSearch Service, Amazon ElastiCache for Redis, Amazon Kinesis Data Streams, Amazon DocumentDB, Amazon Neptune, Apache Kafka (including Amazon MSK), and Babelfish for Aurora PostgreSQL.
AWS Schema Conversion Tool (SCT)
AWS SCT converts database schema and code so an existing application can run on a different engine, and can generate the SQL used to build the converted schema on the target. SCT and DMS work together: SCT copies schemas for homogeneous migrations and converts them for heterogeneous migrations, then either DMS or SCT moves the data itself — DMS traditionally handles smaller relational workloads (under 10 TB) with ongoing replication support, while SCT is primarily used for large data warehouse workloads and does not support ongoing replication.SCT's OLTP schema conversions:
| IBM Db2 for z/OS | Aurora MySQL, Aurora PostgreSQL, MySQL, PostgreSQL. |
| IBM Db2 LUW | Aurora MySQL, Aurora PostgreSQL, MariaDB, MySQL, PostgreSQL. |
| Microsoft Azure SQL Database | Aurora MySQL, Aurora PostgreSQL, MySQL, PostgreSQL. |
| Microsoft SQL Server | Aurora MySQL, Aurora PostgreSQL, Babelfish for Aurora PostgreSQL (assessment reports only), MariaDB, SQL Server, MySQL, PostgreSQL. |
| MySQL | Aurora PostgreSQL, MySQL, PostgreSQL. (MySQL schema and data can migrate to an Aurora MySQL cluster without AWS SCT/DMS at all.) |
| Oracle | Aurora MySQL, Aurora PostgreSQL, MariaDB, MySQL, Oracle, PostgreSQL. |
| PostgreSQL | Aurora MySQL, Aurora PostgreSQL, MySQL, PostgreSQL. |
| SAP ASE | Aurora MySQL, Aurora PostgreSQL, MariaDB, MySQL, PostgreSQL. |
SCT also converts data warehouses (Amazon Redshift, Azure Synapse Analytics, BigQuery, Greenplum, SQL Server, Netezza, Oracle, Teradata, Vertica, and Snowflake all convert to Amazon Redshift), one NoSQL conversion (Apache Cassandra to Amazon DynamoDB), big data frameworks (Apache Hive to Hive on Amazon EMR; Apache HDFS to S3 or HDFS on EMR), and ETL pipelines (Informatica scripts stay on Informatica; SQL Server Integration Services (SSIS) packages convert to AWS Glue or AWS Glue Studio; Teradata BTEQ scripts convert to AWS Glue or Amazon Redshift RSQL; Teradata FastExport/FastLoad/MultiLoad job scripts convert to Amazon Redshift RSQL).
As part of DMS, DMS Schema Conversion automates converting Oracle PL/SQL and SQL Server T-SQL code into the equivalent RDS for MySQL SQL dialect or PL/pgSQL for PostgreSQL; any fragment that cannot be converted automatically is clearly flagged for manual review. The downloadable, standalone AWS SCT client offers the same conversion capability outside of a DMS task.
Data Sources and Targets Preparation
- Back up both the source and target databases before migrating, in case anything goes wrong during the process.
- Write a migration plan covering the data sources and targets, the migration process, a timeline, and a checklist of pre-, during-, and post-migration tasks.
- Configure the target database — tables, indexes, and other objects — to match the structure of the source.
- Clean up the source database beforehand, removing unnecessary data or objects to reduce size and simplify the migration.
- Verify data consistency in both source and target with consistency checks before proceeding.
- Test the migration process against a small subset of data first, to surface issues before migrating everything.
Schema Conversion Methods
Using AWS SCT to determine and apply a schema conversion typically follows this sequence: install SCT (available for Windows, macOS, and Linux); configure it with AWS access keys and source/target connection details; create a project and select the source and target database types (MySQL, Oracle, SQL Server, PostgreSQL, and others are supported); analyze the source schema to surface differences in data types, constraints, indexes, and other objects versus the target; apply the conversion (SCT offers data type mappings, constraint conversions, and index conversions); test the conversion against a small data subset; then migrate the full schema using DMS, a native tool, or another third-party tool.Heterogeneous vs. Homogeneous Migration
A homogeneous migration moves a database between platforms running the same engine — for example, an on-premises MySQL database to an Amazon RDS MySQL instance — and is simpler and lower-risk because no object or data-type conversion is needed. A heterogeneous migration moves a database to a different engine — for example, Oracle to Aurora PostgreSQL — and is more complex, since objects, data types, and other components must be converted for compatibility with the target engine.Choosing between the two depends on engine compatibility (whether the source and target support the same data types and features), the overall complexity of the migration (database size, number of objects, degree of customization), the timeframe (heterogeneous migrations generally take longer due to schema conversion work), and the resources available (heterogeneous migrations often need additional database expertise or tooling).
Migration Execution and Validation
Executing a migration typically proceeds through these steps: configure AWS DMS (replication instance, source and target endpoints, and migration tasks); start the migration so DMS copies data from source to target through the replication instance; monitor the replication instance via the DMS console or CLI while it runs; validate the copied data once the migration completes, comparing source and target for consistency; test the target database with queries, integrity checks, and application-level testing; switch the application over to the target's endpoint once satisfied; and finally decommission the source database once the target is confirmed fully functional.Design and Script
Designing a migration means deciding on the source and target databases, the migration method (full or incremental), and any required schema conversion or data transformation, then choosing the appropriate tool — DMS, SCT, the AWS CLI, or a hand-written script — extracting and transforming the data as needed, writing and thoroughly testing the migration scripts, running them while monitoring progress, validating the migrated data, and finally switching the application over to the new endpoint. Four common scripting approaches, each shown as a worked example below:- AWS DMS task definitions — a replication task is defined declaratively (source/target endpoints, migration type, table mappings, and settings) and submitted with the AWS CLI, e.g. aws dms create-replication-task --replication-task-settings file://dms_migration.yaml.
- AWS SCT scripts — SQL run directly in the SCT SQL editor to stage data, drop/rename tables, and adjust data types and functions for the target engine.
- Python with the AWS SDK (Boto3) — Boto3 wraps AWS service APIs, so a Python script can extract rows from a source engine driver (e.g. mysql.connector), load them into a target driver (e.g. psycopg2), and hand off to other AWS services such as S3 and Redshift for downstream loading.
- Direct SQL scripts — exporting from the source and importing into the target with plain SQL (and, for PostgreSQL, psql meta-commands such as \connect) is a flexible option that can be tailored to specific needs.
Extraction and Migration Scripts
Running migration scripts generally involves obtaining or writing the scripts for the chosen method; configuring the AWS environment ( security groups, IAM roles, network settings) so the scripts can reach the source and target databases; deploying the scripts to an EC2 instance or container, or attaching them to a DMS/SCT task; executing them while monitoring progress and troubleshooting any issues; and validating the target data and updating application configuration once the migration is complete.Verification
After a migration, review the DMS/SCT logs and console output for errors or warnings and resolve them before proceeding; validate that the target schema matches the source schema (using SCT's automatic conversion or manual review); compare the data itself between source and target, using DMS or a third-party comparison tool; test the migrated data's functionality with representative queries and application traffic; monitor the target database's performance and tune settings or configuration as needed; and document the migration process and its verification results for future reference and auditing. See also Backup and Recovery for MySQL's own backup and restore mechanisms, which remain relevant for pre-migration backups of a source database.# CloudFormation template that deploys a VPC, subnet, subnet group, security
# group, and an RDS MySQL instance
Resources:
# Create a VPC for the database
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: MyDatabaseVpc
# Create a subnet for the database
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: "10.0.0.0/24"
AvailabilityZone: "us-west-2a"
Tags:
- Key: Name
Value: MyDatabaseSubnet
# Create a subnet group for the database
DatabaseSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for MyDatabase
SubnetIds:
- !Ref Subnet
# Create a security group for the database
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow traffic to database
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: MyDatabaseSecurityGroup
# Create an RDS instance for the database
Database:
Type: AWS::RDS::DBInstance
Properties:
Engine: mysql
EngineVersion: "8.0"
DBInstanceClass: db.t2.micro
AllocatedStorage: "20"
DBInstanceIdentifier: MyDatabase
MasterUsername: admin
MasterUserPassword: mypassword
DBSubnetGroupName: !Ref DatabaseSubnetGroup
VPCSecurityGroups:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: MyDatabaseInstance
# Deploy the stack with:
# aws cloudformation create-stack --stack-name mydatabase --template-body file://database.yaml# Terraform configuration that deploys a VPC, subnet, security group, and an
# RDS MySQL instance
# Create a VPC for the database
resource "aws_vpc" "database_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "MyDatabaseVpc"
}
}
# Create a subnet for the database
resource "aws_subnet" "database_subnet" {
vpc_id = aws_vpc.database_vpc.id
cidr_block = "10.0.0.0/24"
availability_zone = "us-west-2a"
tags = {
Name = "MyDatabaseSubnet"
}
}
# Create a subnet group for the database
resource "aws_db_subnet_group" "database_subnet_group" {
name = "MyDatabaseSubnetGroup"
subnet_ids = [aws_subnet.database_subnet.id]
}
# Create a security group for the database
resource "aws_security_group" "database_security_group" {
name = "MyDatabaseSecurityGroup"
vpc_id = aws_vpc.database_vpc.id
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "MyDatabaseSecurityGroup"
}
}
# Create an RDS instance for the database
resource "aws_db_instance" "database_instance" {
engine = "mysql"
engine_version = "8.0"
instance_class = "db.t2.micro"
allocated_storage = 20
identifier = "MyDatabase"
username = "admin"
password = "mypassword"
db_subnet_group_name = aws_db_subnet_group.database_subnet_group.name
vpc_security_group_ids = [aws_security_group.database_security_group.id]
tags = {
Name = "MyDatabaseInstance"
}
}
# Deploy with:
# terraform init
# terraform apply# File: dms_migration.yaml
# Describes an AWS DMS full-load replication task from a MySQL source to a
# PostgreSQL target
---
Task:
Name: MySQL-to-PostgreSQL-Migration
SourceEndpoint:
EndpointIdentifier: mysql-source-endpoint
EngineName: mysql
ServerName: mysql-server.example.com
Port: 3306
DatabaseName: mydb
ExtraConnectionAttributes: "ssl_mode=required"
UserName: user
Password: password
TargetEndpoint:
EndpointIdentifier: postgresql-target-endpoint
EngineName: postgresql
ServerName: postgresql-server.example.com
Port: 5432
DatabaseName: mydb
ExtraConnectionAttributes: "sslmode=require"
UserName: user
Password: password
ReplicationInstanceArn: arn:aws:dms:us-west-2:123456789012:rep:my-replication-instance
MigrationType: full-load
TableMappings:
- TableName: mytable
TargetTablePrepMode: doNothing
MigrationSettings:
TargetMetadata:
TargetSchema: public
SupportLobs: true
# Create the replication task from this file:
# aws dms create-replication-task --replication-task-settings file://dms_migration.yaml-- Sample AWS Schema Conversion Tool (SCT) script, run in the SCT SQL editor,
-- that stages a table and converts its data types and functions from an
-- Oracle source schema to a MySQL target schema
-- Work against the source database
USE aws_oracle_source;
-- Stage the conversion in a temporary table
CREATE TABLE temp_table (
id INT,
name VARCHAR(50)
);
INSERT INTO temp_table
SELECT id, name FROM source_table;
DROP TABLE source_table;
ALTER TABLE temp_table RENAME TO source_table;
-- Switch to the target database and adjust data types/functions for MySQL
USE aws_mysql_target;
ALTER TABLE source_table
MODIFY COLUMN id BIGINT,
MODIFY COLUMN name VARCHAR(255);
UPDATE source_table
SET name = CONCAT('Hello, ', name);import boto3
import mysql.connector
import psycopg2
# Connect to the source MySQL database
mysql_conn = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="mydb"
)
# Select the data to migrate
mysql_cursor = mysql_conn.cursor()
mysql_cursor.execute(
"SELECT column1, column2, column3 FROM mytable WHERE condition"
)
mysql_data = mysql_cursor.fetchall()
# Connect to the target PostgreSQL database
pg_conn = psycopg2.connect(
host="localhost",
user="postgres",
password="password",
database="mydb"
)
# Create the target table
pg_cursor = pg_conn.cursor()
pg_cursor.execute(
"CREATE TABLE mytable (column1 INT, column2 VARCHAR(50), column3 TEXT)"
)
# Insert the extracted rows into PostgreSQL
for data in mysql_data:
pg_cursor.execute(
"INSERT INTO mytable (column1, column2, column3) VALUES (%s, %s, %s)",
data
)
pg_conn.commit()
mysql_cursor.close()
mysql_conn.close()
pg_cursor.close()
pg_conn.close()
# Export the migrated PostgreSQL table to S3 as CSV
s3 = boto3.client('s3')
bucket_name = 'mybucket'
key = 'mytable.csv'
pg_conn = psycopg2.connect(
host="localhost",
user="postgres",
password="password",
database="mydb"
)
pg_cursor = pg_conn.cursor()
with open(key, "w") as f:
pg_cursor.copy_expert(
"COPY mytable TO STDOUT WITH DELIMITER ',' CSV HEADER", f
)
s3.upload_file(key, bucket_name, key)
# Load the S3 object into Amazon Redshift via the Redshift Data API
redshift = boto3.client('redshift-data')
redshift_copy_command = (
f"COPY mytable FROM 's3://{bucket_name}/{key}' "
"CREDENTIALS 'aws_iam_role=arn:aws:iam::123456789012:role/MyRedshiftRole' "
"CSV DELIMITER ','"
)
redshift.execute_statement(Sql=redshift_copy_command)-- Direct SQL migration script that transfers data from a MySQL source
-- database to a PostgreSQL target database
-- Select the data to migrate from the MySQL source
USE mydb;
SELECT column1, column2, column3
FROM mytable
WHERE condition;
-- Connect to the PostgreSQL target (psql meta-command)
\connect postgresql://user:password@localhost/mydb
-- Create the target table
CREATE TABLE mytable (
column1 INT,
column2 VARCHAR(50),
column3 TEXT
);
-- Insert the migrated rows
INSERT INTO mytable (column1, column2, column3)
VALUES
(value1, 'value2', 'value3'),
(value4, 'value5', 'value6');