Skip to main content
All articles

Cloud Database Migration Checklist: 20 Steps to a Smooth Cutover

A battle-tested checklist covering schema conversion, data sync, testing, cutover windows, and rollback planning.

Jeff MonfieldFebruary 26, 202613 min read

Why Database Migrations Fail

Database migrations are the highest-risk phase of any cloud adoption or modernization project. Unlike stateless application components that can be redeployed if something goes wrong, databases contain your most valuable asset — your data. A botched migration can mean data loss, extended downtime, corrupted referential integrity, or subtle data inconsistencies that surface weeks later in production. Most database migration failures are not caused by technical limitations but by insufficient planning, inadequate testing, and unrealistic cutover windows.

This checklist distills hard-won lessons from dozens of database migrations across AWS RDS, Azure SQL, Google Cloud SQL, and OCI Autonomous Database. It covers the complete lifecycle from initial assessment through post-migration validation, organized into 20 concrete steps. Each step includes the specific actions to take, common pitfalls to avoid, and how to verify completion. Follow this checklist in order — the sequence matters because each step builds on the work of previous steps.

Phase 1: Assessment and Planning (Steps 1-5)

Step 1: Inventory and Profile Your Source Database

Document everything about your source database before making any decisions about the target. Record the database engine and version, total database size, number of schemas and tables, largest tables by row count and size, stored procedures, functions, triggers, views, sequences, custom data types, character sets and collations, and any engine-specific features in use (partitioning, full-text search, spatial data types, JSON columns).

Profile your workload by capturing at least two weeks of query patterns. Identify the top 20 queries by frequency and by total execution time. Note any queries that use engine-specific syntax or features. Document your current performance baselines: average query latency, peak transactions per second, connection count during peak hours, and storage I/O patterns (read-heavy vs. write-heavy vs. mixed). These baselines are essential for validating that the target database performs acceptably after migration.

Step 2: Choose Your Target Database and Migration Strategy

Decide whether you are performing a homogeneous migration (same engine, e.g., PostgreSQL to Cloud SQL PostgreSQL) or a heterogeneous migration (different engine, e.g., Oracle to PostgreSQL). Homogeneous migrations are dramatically simpler because there is no schema conversion, no SQL syntax differences, and no stored procedure rewriting. If you can keep the same database engine, do so — the reduced risk is almost always worth any theoretical benefits of switching engines.

Choose your migration strategy: offline (dump and restore with scheduled downtime), online (continuous replication with minimal cutover window), or incremental (migrate tables or schemas in batches). Offline migration is simplest but requires the longest downtime window. Online migration using tools like AWS DMS, Azure Database Migration Service, or GCP Database Migration Service minimizes downtime but adds complexity. Document your strategy and get stakeholder sign-off on the expected downtime window before proceeding.

Step 3: Assess Schema Compatibility

For heterogeneous migrations, run a schema assessment using AWS Schema Conversion Tool (SCT), Azure Database Migration Assessment, or Ora2Pg (for Oracle to PostgreSQL). These tools identify incompatible data types, unsupported features, and syntax differences that need manual intervention. Categorize each incompatibility as automatic (the tool can convert it), semi-automatic (requires simple manual adjustment), or manual (requires rewriting).

Common compatibility issues include: auto-increment vs. sequence differences between MySQL and PostgreSQL, Oracle-specific PL/SQL constructs that have no direct PostgreSQL equivalent, SQL Server-specific T-SQL features like CROSS APPLY or MERGE with OUTPUT, differences in NULL handling and string comparison semantics, and varying support for data types like ENUM, JSON, spatial types, and arrays. Document every incompatibility and its resolution before starting the migration.

Step 4: Plan Your Network Connectivity

Database migration requires reliable, low-latency network connectivity between source and target. For on-premises to cloud migrations, evaluate your bandwidth capacity. A 1 TB database migrated over a 100 Mbps connection takes approximately 24 hours for the initial bulk transfer. A 10 TB database over the same connection takes 10 days. If your migration window cannot accommodate the transfer time, consider using physical data transfer services like AWS Snowball, Azure Data Box, or GCP Transfer Appliance for the initial bulk load, followed by online replication to catch up changes made during transit.

For cloud-to-cloud migrations, set up VPC peering, VPN, or private connectivity between the source and target cloud environments. Test the latency and throughput between source and target before the migration. Ensure that firewall rules, security groups, and network access control lists allow traffic on the database port between the source and the migration tool, and between the migration tool and the target.

Step 5: Set Up the Target Environment

Provision the target database with appropriate sizing. Start with the same or slightly larger specifications as the source: equivalent vCPUs, memory, storage IOPS, and storage capacity. You can right-size after migration once you have performance data in the new environment. Configure the target with the same character set, collation, timezone settings, and parameter group settings as the source (adjusted for the target engine if doing a heterogeneous migration).

Set up monitoring on the target from day one. Enable enhanced monitoring, performance insights, or the equivalent for your target platform. Configure alerts for CPU utilization, storage space, replication lag (if using online migration), and connection count. You need to track these metrics throughout the migration to detect issues early.

Estimate RDS target instance costsCompare managed database options across clouds

Phase 2: Schema Migration and Testing (Steps 6-10)

Step 6: Migrate the Schema

Apply the converted schema to the target database. For homogeneous migrations, export the schema using native tools (pg_dump --schema-only, mysqldump --no-data) and apply it to the target. For heterogeneous migrations, apply the converted schema from the assessment tool and manually apply the fixes for any incompatibilities identified in Step 3.

Migrate schema objects in dependency order: first data types and domains, then tables, then indexes, then views, then functions and stored procedures, then triggers. Do not create foreign key constraints or triggers yet — these should be applied after the data migration completes to avoid performance degradation during bulk loading and to prevent trigger side effects on migrated data.

Step 7: Migrate Reference Data and Lookup Tables

Start with small, stable tables: lookup tables, configuration tables, reference data. These are low-risk and let you validate the migration tooling and process before moving to large transactional tables. Verify row counts, spot-check data values, and confirm that character encoding is preserved correctly (this is where many UTF-8 and collation issues surface).

Step 8: Test Application Compatibility

Deploy a test instance of your application pointed at the target database with the migrated schema and reference data. Run your application's test suite against the target. Focus on: queries that use engine-specific syntax, ORM-generated queries that might differ between engines, date and time handling (timezone conversions are a common source of bugs), NULL handling in comparisons and aggregations, and string comparison and sorting behavior (case sensitivity varies between engines and collations).

Fix any application compatibility issues before proceeding to data migration. It is much cheaper to fix these now than during the cutover window when you are under time pressure.

Step 9: Perform a Full Test Migration

Run a complete end-to-end migration with production data (or a recent production backup) to a test target. Time every phase: schema migration, bulk data loading, index creation, constraint application, and replication catch-up (if using online migration). This rehearsal reveals issues that only appear with real data volumes: data type conversion errors on edge-case values, unique constraint violations from data that was valid in the source engine but violates stricter rules in the target, and performance bottlenecks during bulk loading.

Compare row counts between source and target for every table. Run checksum comparisons on critical tables. Execute your top 20 queries from Step 1 and compare execution plans and response times against your baselines. Document any performance regressions and optimize (add indexes, adjust parameters) before the production cutover.

Step 10: Create and Validate a Rollback Plan

Every database migration needs a rollback plan that has been tested. For offline migrations, the rollback plan is typically to revert the application to point at the original source database, which should remain intact during the migration. For online migrations with continuous replication, consider setting up reverse replication from the target back to the source so that data written to the target during the cutover window is not lost if you need to roll back.

Define your rollback criteria: what specific conditions trigger a rollback decision? Common criteria include: data validation failures (row count mismatches, checksum differences), application error rates exceeding a threshold (e.g., 5x normal), query latency exceeding acceptable limits, or the cutover window exceeding the planned duration. Document who has the authority to make the rollback decision and the communication plan for informing stakeholders.

Never skip the rollback plan

The rollback plan must be tested before the production migration. Run through the rollback procedure during your test migration in Step 9. If you cannot roll back successfully in a test, you certainly cannot roll back under the pressure of a failed production migration.

Phase 3: Data Migration (Steps 11-15)

Step 11: Start Continuous Replication (Online Migrations)

For online migrations, start the continuous replication process well before the planned cutover. AWS DMS, Azure DMS, and GCP DMS all support change data capture (CDC) that reads the source database's transaction log and applies changes to the target in near-real-time. Start replication during a low-traffic period and monitor replication lag closely. Allow the initial full load to complete and the replication to reach a steady state before scheduling the cutover.

Common issues during continuous replication include: LOB (large object) columns that require special handling, tables without primary keys that cannot use CDC efficiently, DDL changes on the source that are not replicated automatically, and replication lag spikes during peak traffic periods. Address each of these during the replication validation period, not during the cutover window.

Step 12: Perform Bulk Data Migration (Offline Migrations)

For offline migrations, use the fastest available bulk loading method. Native export and import tools (pg_dump/pg_restore, mysqldump/mysql, SQL Server BACKUP/RESTORE, Oracle Data Pump) are typically faster than generic migration tools for homogeneous migrations. Disable indexes, constraints, and triggers on the target before loading. Use parallel loading for large tables. Monitor the target database's IOPS and CPU during loading to ensure you are not hitting resource limits.

Step 13: Apply Indexes and Constraints

After the bulk data load completes, create indexes on the target. Build indexes in parallel if the target engine supports it (PostgreSQL supports concurrent index creation, MySQL does not for InnoDB). After indexes are built, apply foreign key constraints and validate that they are all satisfied. Then enable triggers. This sequence is critical: building indexes before validating constraints means any constraint violations are caught before the data is considered ready.

Step 14: Validate Data Integrity

Run comprehensive data validation. Compare row counts for every table between source and target. For critical tables, run checksum or hash comparisons on a per-row or per-batch basis. Validate referential integrity by checking that all foreign key relationships are satisfied. Spot-check data values in columns with complex data types (dates, timestamps with timezones, decimal numbers, Unicode strings, binary data). Run your application's data integrity checks or business rule validations against the target.

Step 15: Verify Application Performance

Run your top 20 queries from Step 1 against the target database with the full dataset loaded. Compare response times to your baselines. Identify any queries where performance has regressed significantly. Common causes of regression include: missing indexes (verify all indexes were created successfully), different query planner behavior between engines, statistics not up to date on the target (run ANALYZE or the equivalent), and parameter settings that need tuning for the target environment.

AWS RDS and Aurora Guide

Phase 4: Cutover (Steps 16-18)

Step 16: Prepare for Cutover

Schedule the cutover during your lowest-traffic period. Notify all stakeholders of the maintenance window. Prepare a detailed runbook with timestamps, responsible individuals, and go/no-go checkpoints. Have your rollback plan printed and accessible to everyone involved. Set up a dedicated communication channel (Slack channel, bridge call) for the migration team.

Step 17: Execute the Cutover

For online migrations: stop the application from writing to the source, wait for replication lag to reach zero, perform final data validation, switch the application's database connection string to the target, and restart the application. For offline migrations: stop the application, perform the final data export and import (or apply the last incremental backup), validate data, switch connection strings, and restart.

Monitor the application closely after restart. Check error rates, response times, database connection counts, and query patterns. Have the team ready to execute the rollback plan if the go/no-go criteria from Step 10 are not met within the defined time window.

Step 18: Post-Cutover Validation

Run a final comprehensive validation within the first hour after cutover. Verify that all application functionality works correctly. Check that scheduled jobs, background workers, and batch processes are running against the new database. Monitor for slow queries that might indicate missing indexes or stale statistics. Verify that backup jobs are running successfully on the target.

Phase 5: Post-Migration (Steps 19-20)

Step 19: Optimize and Right-Size

After one week of production operation on the target, review performance metrics. Right-size the target instance based on actual utilization — you may have over-provisioned for safety during migration. Review and optimize slow queries using the target engine's query analysis tools. Set up automated maintenance tasks: statistics updates, vacuum (PostgreSQL), index maintenance, and log rotation.

Step 20: Decommission the Source

Keep the source database running in read-only mode for at least two weeks after cutover as a safety net. After the stabilization period, take a final backup of the source database and store it in durable storage (S3, Azure Blob, GCS) for compliance and disaster recovery. Then decommission the source database instance. Update all documentation, runbooks, and architecture diagrams to reflect the new database location.

Migration timeline

A well-planned database migration typically takes 4-8 weeks from assessment to decommission for databases under 1 TB. Larger databases or heterogeneous migrations can take 3-6 months. Do not compress the timeline — the planning and testing phases catch the issues that cause migration failures.

Compare database services across cloudsMulti-Cloud Database Comparison Guide

Written by Jeff Monfield

Cloud architect and founder of CloudToolStack. Building free tools and writing practical guides to help engineers navigate AWS, Azure, GCP, and OCI.

Disclaimer: This article is for informational purposes. Cloud services and pricing change frequently; always verify with official provider documentation. AWS, Azure, GCP, and OCI are trademarks of their respective owners.