Skip to main content

Command Palette

Search for a command to run...

MySQL to PostgreSQL: A Hands-On AWS DMS Migration Guide with AWS RDS Aurora

Updated
7 min read

Database migration

Databases are important part of any applications. But due to various reasons like cost, compliance, application compatibility etc. database migrations are required. In this blog we will discuss importance of doing database migration in the right way and using AWS DMS for this purpose with a hands-on example.

Why a live database migration is challenge

During Live migrations it is required to keep the database operational during the transition, which risks data inconsistency, extended downtime, and increased manual effort. Database migration is challenge due to various reasons like:

  • Data Type Differences: Handling discrepancies between different data types like MySQL and PostgreSQL has certain difference in schema and conventions.

  • Schema Conversion: Adapting schema definitions and constraints to match PostgreSQL requirements.

  • Downtime: Potential service disruption if the database is live and critical.

  • Manual Effort: Increased risk of human error and additional time in manual configuration.

  • Data Integrity: Ensuring consistency and accuracy during data transformation and transfer.

Different ways to perform database migration

There are different ways to perform database migration. All of these approach have their own pros and cons.

One of the most popular approach is using SQL Dumps. Here we Use mysqldump to export data and import into PostgreSQL but this is manual and error prone. Similarly, various ETL tools like Talend or Apache NiFi can be used and there are various specialized utilities like pgloader for automated schema and data conversion as well.

But all these approaches have significant risks of data loss, downtime and human error. This is where AWS DMS comes in picture.

What is AWS DMS?

AWS DMS is a managed service from AWS that facilitates database migration to AWS. It supports both homogeneous (same database engine) and heterogeneous (different database engines) migrations.

When to Use AWS DMS

  • Migrating on-premises databases to the cloud.

  • Modernizing or consolidating databases across different environments.

  • Enabling continuous data replication during live migrations with minimal downtime.

Benefits of AWS DMS

  • Cost-Efficient: Reduces overhead with a managed solution.

  • Minimal Downtime: Supports continuous data replication, ensuring business continuity.

  • Simplified Management: Automates replication and offers robust monitoring tools.

  • Flexibility: Adapts to various migration scenarios, whether homogeneous or heterogeneous.

How to setup DMS

Migrating databases between different engines or environments can be challenging. As discussed earlier, out of various approaches AWS DMS provides the most robust way to perform this task. Let’s setup a DMS service using terraform.

Automating AWS DMS Cluster Deployment with Terraform


AWS Database Migration Service (DMS) setup with Terraform makes the process very highly automated and reproducible. In this lab, we’ll create a full Terraform configuration that provisions a DMS replication instance, configures source and target endpoints, defines a replication task for migrating an entire schema, and sets up the necessary IAM roles for seamless operation.


1. AWS Provider Setup

Terraform starts by configuring the AWS provider. This tells Terraform where to deploy your resources. Adjust the region as needed:

provider "aws" {
  region = "us-east-1"  # Adjust region as needed
}

2. Creating the DMS Replication Instance

The replication instance is the core compute resource for DMS. It handles the data migration process. Here’s the complete resource configuration:

resource "aws_dms_replication_instance" "dms_instance" {
  replication_instance_id   = "dms-instance"
  replication_instance_class = "dms.t3.medium"  # We are using Smallest available instance class for DMS to control cost.
  allocated_storage         = 50 # This is also smallest possible value
  publicly_accessible       = true # You can keep it false in prod env
}

In this code we are creating dms-instance and uses the dms.t3.medium class. We are allocatting 50 GB of storage.


3. Configuring DMS Endpoints

Endpoints specify where data is coming from (source) and where it is going (target). This example uses an Aurora MySQL database as the source and an Aurora PostgreSQL database as the target.

Source Endpoint – Aurora MySQL

resource "aws_dms_endpoint" "source_mysql" {
  endpoint_id   = "source-mysql-endpoint"
  endpoint_type = "source"
  engine_name   = "mysql"

  username      = "admin"
  password      = "SUPERSECRET"
  server_name   = "rds-mysql-url.us-east-1.rds.amazonaws.com"
  port          = 3306
  database_name = "sample_db"
}

Target Endpoint – Aurora PostgreSQL

resource "aws_dms_endpoint" "target_postgres" {
  endpoint_id   = "target-postgres-endpoint"
  endpoint_type = "target"
  engine_name   = "postgres"

  username      = "master"
  password      = "SUPERSECRET"
  server_name   = "rds-postgres-url.us-east-1.rds.amazonaws.com"
  port          = 5432
  database_name = "sample_db"
}

Here we are setting the source and target. We specify the PostgreSQL connection details ensuring that DMS knows where to load the data.

4. Defining the DMS Replication Task

The replication task orchestrates the data migration. This task defines what to migrate, the migration type, and includes detailed settings to control the behavior during the migration.

resource "aws_dms_replication_task" "dms_task" {
  replication_task_id      = "mysql-to-postgres-migration"
  replication_instance_arn = aws_dms_replication_instance.dms_instance.replication_instance_arn
  source_endpoint_arn      = aws_dms_endpoint.source_mysql.endpoint_arn
  target_endpoint_arn      = aws_dms_endpoint.target_postgres.endpoint_arn

  migration_type = "full-load"  # Use "full-load-and-cdc" for ongoing changes

  table_mappings = <<EOF
{
  "rules": [
    {
      "rule-type": "selection",
      "rule-id": "1",
      "rule-name": "IncludeAllTables",
      "object-locator": {
        "schema-name": "sample_db",
        "table-name": "%"
      },
      "rule-action": "include"
    }
  ]
}
EOF

  replication_task_settings = <<EOF
{
  "TargetMetadata": {
      "TargetSchema": "",
      "SupportLobs": true,
      "FullLobMode": false,
      "LobChunkSize": 64,
      "LimitedSizeLobMode": true,
      "LobMaxSize": 32,
      "InlineLobMaxSize": 0,
      "LoadMaxFileSize": 0,
      "ParallelLoadThreads": 0,
      "ParallelLoadBufferSize": 0,
      "BatchApplyEnabled": false,
      "TaskRecoveryTableEnabled": false
  },
  "FullLoadSettings": {
      "TargetTablePrepMode": "DO_NOTHING",
      "CreatePkAfterFullLoad": false,
      "StopTaskCachedChangesApplied": false,
      "StopTaskCachedChangesNotApplied": false,
      "BatchApplyEnabled": false,
      "BatchApplyPreserveTransaction": false,
      "BatchApplyTimeoutMin": 0,
      "BatchApplySkipErrorTables": false
  },
  "Logging": {
      "EnableLogging": true
  }
}
EOF
}

Important details:

  • Task Identification: The replication_task_id uniquely labels the task.

  • Migration Type: It uses full-load to migrate the entire schema and data at once.

  • Table Mappings: The JSON mapping rule ensures that all tables in the CompanyDB schema are included.

  • Task Settings: These JSON blocks provide detailed configurations like LOB handling and logging options, ensuring that the task behaves as expected.


5. Configuring IAM Roles for DMS

AWS DMS requires specific IAM roles to interact with your VPC and CloudWatch logs. Two roles are created—one for VPC management and another for CloudWatch logging.

IAM Role for VPC Management

resource "aws_iam_role" "dms_vpc_role" {
  name = "dms-vpc-role"
  assume_role_policy = jsonencode({
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "dms.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "dms_vpc_role_attach" {
  role       = aws_iam_role.dms_vpc_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
}

Here, we are granting the DMS service permission to assume the role.

IAM Role for CloudWatch Logs

Here we are handling the logging permissions. Policy Attachment ensures DMS can write logs to CloudWatch for monitoring and troubleshooting.

resource "aws_iam_role" "dms_cloudwatch_logs_role" {
  name = "dms-cloudwatch-logs-role"
  assume_role_policy = jsonencode({
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "dms.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "dms_cloudwatch_logs_role_attach" {
  role       = aws_iam_role.dms_cloudwatch_logs_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSCloudWatchLogsRole"
}

Creating the DMS cluster

Let’s apply the terraform configuration and observe the changes.

terraform apply

Observe the created DMS service

If everything is correct then it should start creating the DMS replication instance.

Pre-migration

Pre-migration assessment is important process to analyze the source database to identify compatibility issues, estimate migration effort, and plan the migration strategy.

Why is it important?

  • Detects schema and data type mismatches.

  • Estimates required changes and risks.

  • Helps choose the right tools and migration path.

  • Reduces surprises during migration.

Once you hit create migration assessment, it will start the process and give you the migration assessment result.

Reviewing migration results

After migration, AWS DMS can store detailed logs and migration reports in an S3 bucket. When you are reviewing them you can focus on these points:

  • Verify which tables and rows were migrated.

  • Identify any skipped or failed records.

  • Troubleshoot issues using detailed error logs.

  • Ensure data consistency between source and target.

This is how a sample report looks like

Finally, let’s start migration

Now comes the exciting part—starting the migration!

With everything configured and validated, kicking off the DMS task sets your data in motion. Watch as your tables begin flowing from MySQL to PostgreSQL, live and in real time. It’s the moment where planning turns into action, all with minimal downtime and full control via DMS.

Once this task is over, then your database has successfully migrated from Mysql to Postgres Sql. You can celebrate now! Yeyyy!

More from this blog

C

Chandradeo Arya's Tech Blog

12 posts

DevOps & Cloud Instructor, Curriculum Author, Solutions & AI Architect