Azure Database Migration Service: Moving Databases to Azure With Minimal Downtime
A complete, plain-English guide to assessment, schema work, offline and online migrations, how the service moves data behind the scenes, how to cut over safely, and the mistakes that sink migration projects.
Moving house is a good picture of a database migration. You have to decide what to take and what to throw away, pack things in the right boxes, move them without breaking anything, and unpack in a new place where everything still has to work on the first morning. The hard part is not carrying the boxes. The hard part is that you still need to cook breakfast in the old kitchen until the moment the new one is ready.
Databases are the same, only the stakes are higher. A company cannot close for a weekend because its orders, patients or payments live in the database being moved. Azure Database Migration Service, often shortened to DMS, is the Azure service built to carry this load. It moves data from an existing database to an Azure database, and for many sources it keeps the new copy up to date while the old one is still in use, so the final switch takes minutes instead of days. In this guide you will learn what it does, how the pieces fit, what happens inside, how to plan, secure and monitor a migration, how to cut over and roll back, and which mistakes to avoid.
1What Azure Database Migration Service Is and Why It Exists
Start with the plain meaning of a migration, then see where this service fits in the Azure toolbox.
What a database migration is
A database migration is the act of moving a database, with all its data and the programs stored in it, from one system to another. The source might be a server in your own office, a virtual machine in another cloud, or an older version of a product. The target might be a managed Azure database, where Microsoft runs the machines for you. The job is not just copying bytes. The new system must hold the same information, behave the same way for the applications that depend on it, and be proven correct before anyone relies on it.
What the service does
Azure Database Migration Service is a managed service that moves the data and, in several scenarios, keeps it synchronized until you are ready to switch. It supports two broad styles. In an offline migration, the source is frozen at some moment, the data is copied, and the application is down until the copy finishes. In an online migration, the first copy happens while the source stays in use, and the service then keeps applying new changes to the target. When the gap is nearly zero, you pause the application briefly, apply the last changes and switch. The longer path is the same, but the downtime shrinks from hours to minutes.
An offline migration is like emptying a whole shop overnight into a truck and re-opening in the new building the next day: the shop is closed in between. An online migration is like moving the stock shelf by shelf while the shop keeps trading, then carrying across the last few items at closing time, so customers barely notice the change of address.
What it is not
DMS is not a magic converter of any database into any other. It does not rewrite your application. It does not decide which Azure database suits you. For migrations between different engines, such as Oracle to PostgreSQL, the structure and code must usually be converted with other tools first, and DMS then helps move the data. It is the dependable moving crew, not the architect and not the interior designer.
The problems it solves
Migrations used to rely on hand-written scripts, one-off backups copied on disks, and custom replication setups that only one engineer understood. DMS packages the common paths into a service with a guided process, progress tracking and repeatable steps. It removes the need to build and maintain your own copy machinery, and it lets teams migrate many databases in waves with the same method every time.
Use DMS when your source and target are a supported pair, when downtime matters, or when you have many databases to move in a repeatable way. For tiny databases you can afford to take offline, a simple backup and restore may be enough.
2Where It Came From: How Databases Used to Move
Every good tool answers an older pain. Looking at how teams moved databases before such a service makes its design obvious.
The weekend outage
The oldest method is also the simplest: schedule a maintenance weekend, stop the application, take a full backup, copy the file to the new server, restore it, test it and switch. It works, and for small systems it is still perfectly fine. But as databases grew to hundreds of gigabytes and then terabytes, the copy step alone took many hours, and a weekend was no longer enough. Businesses that ran around the clock could not accept any outage at all.
Extract, transform and load
Another approach was to treat the migration like a data pipeline: read each table, convert it as needed and write it into the new system. These extract, transform and load jobs were flexible but slow, needed careful ordering of tables and could not easily keep up with changes made during the move. Fixing a missed row meant re-running parts of the job.
Replication and change capture
To shrink downtime, engineers learned to use database replication: set up the new server as a copy that continuously receives changes from the old one. When the copy has caught up, switch over. This works very well but needs deep knowledge of each database engine, careful settings, and constant watching. Mistakes were costly, and each engine had its own quirks.
The cloud changes the stakes
Moving to the cloud made all of these problems more common. Companies had to move many databases, over networks that were slower than disks inside a data center, to targets managed by someone else. They wanted a service that handled the connection, the copying and the catching up in a standard way. Azure Database Migration Service grew from that need, first as a service that you deployed into your own virtual network with tiers for offline and online work, and later as a more integrated experience tied to assessment tools and the Azure portal.
| Method | How it works | Weakness |
|---|---|---|
| Weekend backup and restore | Stop, back up, copy, restore, switch | Downtime grows with database size |
| Hand-built data pipelines | Read tables, convert, write to target | Slow, hard to keep in sync, easy to miss rows |
| Self-managed replication | Target subscribes to source changes | Needs expert setup per engine, fragile |
| Managed migration service | Service copies data and applies changes with monitoring | Learning its prerequisites and supported paths |
The names, tiers and tools around Azure migration have been reorganized more than once, with older “classic” experiences being retired in favor of newer ones. The ideas in this guide stay stable, but always confirm current names and supported scenarios in the official documentation before you start.
3Core Concepts: The Vocabulary of a Migration
A short list of terms appears in every migration plan. Learn them once and the rest of the documentation will read easily.
Source and target
The source is where data lives now. The target is the Azure database that will hold it. A pair of source and target types decides which tools and modes are possible.
Offline migration
One-time copy. The source should not change during the copy, so the application is paused. Simple and predictable.
Online migration
Initial copy plus continuous change replay. The source stays in use until the cutover moment.
Cutover
The planned switch: stop writes on the source, let the last changes arrive, then point applications to the target.
Assessment
A scan of the source that lists features in use, finds blockers and recommends a target and size before any data moves.
Schema
The tables, columns, indexes, views and programs inside a database, as opposed to the rows of data stored in them.
Integration runtime
A small program you install near the source, which reads data or backup files and sends them securely to Azure on the service’s behalf.
Lag
How far behind the target is compared with the source. Cutover is safe when lag reaches near zero.
Homogeneous and heterogeneous
A homogeneous migration keeps the same database engine, such as SQL Server to Azure SQL or PostgreSQL to Azure Database for PostgreSQL. Most data types and language features carry over, so the work is mostly about moving data and a few settings. A heterogeneous migration changes engine, such as Oracle to PostgreSQL. Here the structure and the code stored in the database, such as procedures, usually need conversion, which is a significant project of its own.
Schema first, data second
A database is two things: its shape and its contents. For many paths the shape must exist on the target before data can be copied into it. Backup-based migrations carry both together, because a backup contains everything. Table-copy migrations often need the target schema deployed first, using separate tools. Keep this difference in mind when you read a migration path; it decides how many steps you must run.
Instance objects versus database objects
Databases do not live alone. Around them are logins, jobs, alerts, linked server definitions and settings that belong to the server. These instance-level objects are not inside the database and often do not travel with it. They must be inventoried and recreated deliberately on the target. Forgetting them is among the most frequent causes of a failed first morning.
A migration has three timelines
The first is the data timeline: how long the initial copy and catch-up take. The second is the project timeline: assessment, preparation, testing and approvals, usually much longer than the data copy. The third is the application timeline: the changes to connection strings, drivers and code that must be ready when the data is. Good plans track all three.
4Supported Paths and How to Choose
Not every source works with every target in every mode. Choosing the path early saves you from discovering a limit halfway through.
The common paths
| Source | Typical Azure target | Modes usually offered | Main method behind the scenes |
|---|---|---|---|
| SQL Server | Azure SQL Managed Instance | Offline and online | Backup files in storage restored, with logs replayed for online |
| SQL Server | SQL Server on Azure Virtual Machines | Offline and online | Backup restore and log replay |
| SQL Server | Azure SQL Database | Offline; online in some experiences | Table-level data copy after the schema is deployed |
| PostgreSQL | Azure Database for PostgreSQL | Offline and online | Initial copy plus logical replication of changes |
| MySQL | Azure Database for MySQL | Offline and online | Initial copy plus replay of the change log |
| MongoDB | Azure Cosmos DB for MongoDB | Offline and online | Collection copy plus change stream or operation log |
| Oracle | Azure Database for PostgreSQL or Azure SQL | Depends on tooling | Schema conversion tool first, then data movement |
Supported source versions, target services and modes are updated often, and some PostgreSQL and MySQL paths are now offered through built-in migration features of the target services themselves. Treat the table above as the usual shape, and check the current compatibility list before you commit to a plan.
Which target for a SQL Server source
For SQL Server, the target choice decides the method. Azure SQL Managed Instance is the closest match for systems that use agent jobs, cross-database queries and other instance features, and it accepts backup-based migration with log replay, which handles even large databases with short downtime. SQL Server on a virtual machine is the choice when you need full control or a feature the managed options lack. Azure SQL Database is a single-database service for applications that do not need instance features, and its migrations copy table data after the schema is prepared.
Choosing offline or online
Downtime is acceptable
The database is small or the business can close for a window. Fewer moving parts, easier to verify, lower risk of subtle sync issues.
Downtime is costly
The database is large, runs around the clock or the cutover window is measured in minutes. Needs more preparation and careful monitoring.
By waves
Small, quiet databases go offline in early waves. Critical systems get online migrations later, using the experience gained.
Companion tools
DMS rarely works alone. Azure Migrate discovers servers and databases, assesses readiness and estimates cost. The SQL assessment tools check compatibility and recommend a target size from collected performance data. SQL Server Migration Assistant, called SSMA, converts structure and code from Oracle and other engines to SQL Server and Azure SQL. Open-source tools help convert Oracle to PostgreSQL. Azure Data Studio and the Azure portal host the guided migration experience, although tooling is moving between these front ends over time, so confirm what is current.
5Architecture and Components
The picture below shows the usual building blocks of a SQL Server to managed target migration. Other engines look similar, with different parts doing the copying.
flowchart LR
subgraph SRC["Source environment"]
DB["Source database server"]
SHARE["Backup files on a network share"]
SHIR["Self hosted integration runtime"]
end
subgraph AZ["Azure"]
DMS["Database Migration Service"]
BLOB["Azure Blob Storage container"]
TGT["Target: managed instance, VM or database"]
PORTAL["Azure portal or migration tool"]
end
DB --> SHARE
SHARE --> SHIR
SHIR -->|"Encrypted upload"| BLOB
PORTAL -->|"Create and monitor migration"| DMS
DMS -->|"Read backups, restore, replay logs"| BLOB
DMS --> TGT
BLOB --> TGT
APP["Applications"] -.->|"Connection string switched at cutover"| TGT
The Database Migration Service resource
The service itself is an Azure resource you create in a subscription and region. It acts as the coordinator. You tell it which source, which target and which databases; it keeps the plan, runs the steps, records progress and reports errors. Depending on the path, it also performs work itself, such as reading backups from storage and telling the target to restore them.
The integration runtime
Azure cannot reach inside your private network on its own. For paths that read files or data from the source, a small program called the self-hosted integration runtime is installed on a machine near the source. It has network access to the file share or database, and it makes outbound encrypted connections to Azure, so you do not need to open inbound holes in your firewall. It reads backup files or data and sends them to Azure storage or to the target.
Azure Storage as the staging area
Many SQL Server migrations use a Blob Storage container as a waiting room. Backup files are placed there, either by the runtime or by your own tools, and the service restores from it. Storage is cheap, durable and fast to read, and it lets the upload and the restore overlap in time. The container should be private, with access given only to the identities involved.
The target
The target is a normal Azure database you created beforehand. For migrations that restore backups, the target is not usable by applications until the final cutover completes, because the database sits in a special restoring state. For table-copy migrations, the target is online, but should not be used by applications until you finish.
Assessment and tracking
Next to the data path sits the planning path. Assessment tools produce readiness and sizing reports. The migration tool then shows each database’s state during the move. These two paths use the same inventory of databases, so keep it up to date from the first discovery run to the final completed state.
Place the integration runtime machine on the same fast network as the source database and backup share. A runtime on a slow or distant network turns every upload into a bottleneck.
6Internal Working: How a Migration Really Happens
Understanding what the service does behind the progress bar explains almost every prerequisite and every error message you will meet.
Offline migration: copy and verify
In an offline migration the source is not expected to change during the copy. For backup-based paths, you take a full backup of each database, place it where the service can read it, and the service asks the target to restore it. For table-copy paths, the service reads each table in chunks, writes the chunks to the target in parallel and records which tables are done. After the last table finishes, the target is ready. Because nothing moves afterwards, there is nothing to keep in sync, and the failure modes are few: network trouble, a full target disk, or a type that cannot be stored.
Online migration: copy, catch up, hold
An online migration has three phases. First is the initial load, a consistent copy of the data as it was at a chosen point. While that copy runs, users keep changing the source. Second is the catch-up phase, in which the service finds the changes made since the initial point and applies them to the target in order. Third is the hold phase, where the service keeps applying new changes as they happen, so the target stays only seconds or minutes behind. You choose when to leave the hold phase by starting the cutover.
stateDiagram-v2 [*] --> Preparing Preparing --> InitialLoad : Connections and prerequisites OK InitialLoad --> CatchUp : Base copy finished CatchUp --> ReadyForCutover : Lag near zero ReadyForCutover --> ReadyForCutover : New changes keep arriving and applying ReadyForCutover --> CuttingOver : You start cutover after pausing writes CuttingOver --> Completed : Final changes applied and target opened InitialLoad --> Failed : Error CatchUp --> Failed : Error Failed --> Preparing : Fix and retry Completed --> [*]
How changes are discovered
Every database engine records changes in some kind of log. The service reads that log, or a feed built from it, and replays the changes on the target. The details differ by engine, and each has prerequisites on the source.
| Engine | Where changes come from | Prerequisites to expect |
|---|---|---|
| SQL Server to managed instance or VM | Transaction log backups taken regularly and restored in order | Full backup with checksums, an unbroken chain of log backups, backups in a location the service can read |
| SQL Server to Azure SQL Database (table copy) | Change tracking or log reading, depending on experience | Source permissions, schema already deployed, primary keys on tables |
| PostgreSQL | Logical replication from the write-ahead log | Logical decoding enabled, replication permissions, primary keys for updates and deletes |
| MySQL | Binary log | Binary logging on, row-based format, enough log retention |
| MongoDB | Operation log or change streams | Replica set mode, enough oplog size, permissions to read it |
Backup-based migration and log replay
For SQL Server to a managed instance, the idea is clever and simple. The target database is created in a restoring state. The full backup is restored first. Then each log backup is restored one after another, which brings the target forward in time. The database never comes online during this period, so nobody can write to it and corrupt the chain. When you start cutover, you take a final log backup from the source after stopping writes, the service restores it, and then the database is brought online. The size of that final backup, and the time to upload and restore it, is your downtime.
Table-copy migration and ordering
For migrations that copy tables, the service must respect the order in which data can be loaded, since foreign keys require parent rows to exist before child rows. A common approach is to disable constraints during load and re-enable them afterward, or to load tables in dependency order. The service typically reads in batches, writes with bulk operations and records per-table counts. Tables without a primary key cause trouble in online mode, because there is no reliable way to find which target row an update or delete should affect.
Data types and conversions
Even inside one engine family, some types need care. Time zone handling, very large text, binary columns, spatial types, encrypted columns and user-defined types can behave differently or be unsupported in a given path. The assessment report lists these. Fix them before the migration, not after.
Idempotence and retries
Good migration engines are built to retry. If a batch fails halfway, the service re-applies it safely, so you do not end up with duplicate rows. This is why statuses like “failed” are often temporary: fix the cause, such as a full disk or a closed port, and retry from the last safe point instead of starting over.
Each rule, such as keys on every table, unbroken log chains or row-based binary logs, exists because the service must be able to identify every change and replay it exactly once. Skipping a rule does not save time; it moves the failure to a worse moment.
7Data Flow and Lifecycle: From Assessment to Decommission
Follow one database from discovery to retirement of its old home and the whole method becomes concrete.
sequenceDiagram
participant Ops as Migration team
participant Src as Source SQL Server
participant IR as Integration runtime
participant St as Blob Storage
participant DMS as Migration service
participant Tgt as Target managed instance
Ops->>Src: Take full backup with checksum
IR->>St: Upload backup files
Ops->>DMS: Start migration for database
DMS->>Tgt: Create database in restoring state
DMS->>St: Read full backup
DMS->>Tgt: Restore full backup
loop Every few minutes
Src->>IR: New log backup
IR->>St: Upload log backup
DMS->>Tgt: Restore next log backup
end
Ops->>Src: Stop application writes, final log backup
IR->>St: Upload final log
Ops->>DMS: Start cutover
DMS->>Tgt: Restore last log and bring database online
Ops->>Tgt: Switch applications and validate
The lifecycle in stages
Discover and assess
List servers and databases, run compatibility and sizing checks and collect performance data over a full business cycle.
Decide and design
Pick the target, size, network layout, migration mode and wave order. Agree a cutover window and a rollback plan.
Prepare
Build the target and network, deploy schemas or conversions, set up the integration runtime and storage, and copy logins, jobs and settings.
Rehearse
Run the full process on a copy, measure times, test the application and fix issues.
Migrate
Start the real migration, monitor lag and watch for errors until the target is ready.
Cut over
Pause writes, finish the sync, switch connection strings, validate and reopen the application.
Stabilize and retire
Monitor performance, keep the source read-only for a fallback period, then archive and shut down the old system.
What happens to the source after cutover
A source that is still writable after the switch is dangerous: someone may connect to the old server by habit and quietly create data that exists nowhere else. After cutover, set the source to read-only or take it offline from the application network, but keep it intact for a defined period so you can compare results or roll back. After that period, take a final backup, store it according to your retention rules and decommission the server.
The data in motion
While the migration runs, data exists in at least three places: the source, the staging storage and the target. Treat each as sensitive. Storage should be private and encrypted, temporary access should be removed when the migration ends, and backup files left over in the staging container should be deleted once you no longer need them.
8Assessment and Planning: The Work Before the Work
Most migration failures are planning failures. A good assessment answers three questions: will it work, how big should the target be, and in what order should we move things?
Inventory first
Build a list of every database, its size, owner, business importance, applications that use it, peak usage times and allowed downtime. Add the instance-level items: logins, jobs, linked servers, mail profiles, certificates, scheduled tasks on the server, and any file shares the database uses. Surprises in this list are cheap to fix now and expensive to discover during cutover.
Compatibility assessment
Run an assessment tool against each source. It reports blockers, which are features not supported on the target and must be changed, and warnings, which are behaviors that differ. It also shows whether the database is ready for each target option, such as managed instance, virtual machine or single database. Treat the report as a task list with owners and dates.
Sizing the target
Sizing from the source hardware is a common mistake, because old servers are usually oversized for peak load or undersized after years of growth. Better to collect real performance counters, such as processor use, memory, input and output and log rate, for at least a full business cycle, and let the sizing tool recommend a target. Add headroom, and plan to review after go-live.
Grouping into waves
Do not migrate everything at once. Group databases into waves: first a small pilot of low-risk databases to learn the process, then medium systems, then critical ones. Keep databases that depend on each other, such as two that join across servers, in the same wave. Order waves by business risk, not by alphabetical list.
Pilot
Three to five small, non-critical databases. Goal: prove the network, tools, permissions and runbook.
Low risk
Internal tools and reporting databases with tolerant users. Goal: build speed and confidence.
Medium risk
Departmental systems with defined windows and some dependencies. Goal: refine online migration practice.
Critical
Core transactional systems moved with online migration, rehearsals and full rollback plans.
A worked time estimate
Suppose you must migrate a 2 terabyte database over a network link that delivers 500 megabits per second. That is 62.5 megabytes per second at best. Two terabytes is about 2,000,000 megabytes, so the pure transfer takes 2,000,000 divided by 62.5, which is 32,000 seconds, almost nine hours. Real links never run at full speed, so assume 70 percent efficiency, which gives 43.75 megabytes per second, and the transfer takes about 45,700 seconds, a little under thirteen hours. Next consider the changes during that time and afterward. If the database changes by 5 percent a day, that is 100 gigabytes of log data a day, or 100,000 megabytes. At 43.75 megabytes per second, catching up one day of changes takes about 2,290 seconds, around 38 minutes. Good news: the catch-up is much faster than the first copy, so the target will converge. Finally, think about cutover. If the last log backup is about 2 gigabytes, uploading it takes roughly 46 seconds, and adding restore and checks the downtime could land around ten minutes. Compare that with the thirteen hours an offline move would need.
| Step | Calculation | Result |
|---|---|---|
| Raw speed | 500 Mbps divided by 8 | 62.5 MB per second |
| Realistic speed | 62.5 x 0.70 | 43.75 MB per second |
| Initial copy time | 2,000,000 MB / 43.75 | about 45,700 seconds, nearly 13 hours |
| Daily change volume | 5 percent of 2 TB | 100 GB per day |
| Daily catch-up time | 100,000 MB / 43.75 | about 38 minutes |
| Final log upload at cutover | 2,000 MB / 43.75 | about 46 seconds |
When the first copy would take weeks, consider shipping data on an Azure Data Box device and use online migration only to catch up the changes. Seeding by device turns a multi-week upload into days.
9Schema and Code Conversion
The data is the heavy part, but the shape and the stored code are where subtle bugs hide. How much work this is depends on whether you are changing engines.
Same engine: mostly carry over
When the source and target are the same engine family, the schema usually moves with little change. For backup-based paths, the database is restored whole, so tables, indexes, procedures, views, functions and permissions arrive together. For table-copy paths, you deploy the schema first, using a tool that extracts and applies the definitions, then let the service load the data. Check compatibility levels, collations and special features, since defaults can differ between the old server and the managed target.
Different engine: convert and rewrite
When the engine changes, structure and code need conversion. A conversion tool reads the source schema and produces an equivalent for the target, mapping data types, rewriting procedures and flagging items it cannot convert automatically. Typical hard spots are stored procedures with engine-specific features, packages and sequences, date and time functions, case sensitivity rules, empty-string versus null behavior, and error handling styles. Expect to hand-fix a percentage of code, and budget time for testing every converted routine.
| Item | Same-engine move | Cross-engine move |
|---|---|---|
| Tables and columns | Carry over directly | Data types mapped, some columns changed |
| Indexes and keys | Carry over | Recreated; options may differ |
| Stored procedures and functions | Carry over, test behavior | Converted, often with manual repair |
| Triggers and views | Carry over | Converted and tested one by one |
| Users and permissions | Often map by name | Rebuilt using the target’s model |
| Application queries | Usually unchanged | May need rewriting for dialect differences |
Instance-level objects
Do not forget what lives outside the database: server logins and their passwords or identities, agent jobs, alerts, linked servers, credentials, mail profiles and server settings. For SQL Server paths, scripts that recreate these on the target are a normal part of the plan. Logins in particular need care, because a database user without a matching login becomes an orphan and cannot connect. Mapping logins to Microsoft Entra identities during migration is a good time to improve security.
Encrypted databases
If a source database uses transparent data encryption, its backups can only be restored where the matching certificate or key exists. Plan to export the certificate securely and import it on the target side, or switch the target to a managed key arrangement and re-encrypt after the move. Never send certificates through email or store them beside the backups.
Keep a conversion log
Record every change made during conversion: what, why, who and when. The log helps testers focus, helps future teams understand differences and is the evidence that a hand fix did not silently change business rules.
A converted procedure that compiles is not proof that it behaves the same. Rounding, null handling, sorting and time zones are classic places where results differ. Run side-by-side comparisons on realistic data.
10Networking and Connectivity
Many stalled migrations are stuck on a closed port or a missing route, not on the data. A clear network plan keeps the project moving.
flowchart LR
subgraph ONP["On premises or other cloud"]
SRV["Source database server"]
IRM["Integration runtime machine"]
FWL["Corporate firewall"]
end
subgraph AZV["Azure virtual network"]
PE1["Private endpoint to storage"]
TG["Target managed database"]
end
CONN["ExpressRoute or site to site VPN"]
SRV --> IRM
IRM --> FWL
FWL -->|"Outbound HTTPS only"| CONN
CONN --> PE1
CONN --> TG
PE1 --> ST["Blob Storage staging container"]
ST --> TG
Connections you need
Source to integration runtime
The runtime must reach the database port, such as 1433 for SQL Server, and the backup share. Keep this on the local network.
Runtime to Azure
Outbound encrypted connections to the migration service and to storage. Allow the required Azure addresses and names on the firewall.
Service to target
The service must reach the target database, which may be inside a virtual network or behind firewall rules.
Applications to target
Prepare this before cutover. Applications, jobs and reports must be able to reach the new endpoint and resolve its name.
Bandwidth and latency
Throughput is limited by the slowest link. Measure it with a real file, not with a speed test to a random site. A dedicated ExpressRoute circuit gives steady speed and low delay, while a VPN over the internet is cheaper but shares capacity. Large uploads can also hurt other users of the same link, so schedule heavy transfers outside business hours or limit bandwidth.
Private access to storage and targets
For sensitive data, keep staging storage and targets off the public internet. Use private endpoints, restrict storage to the identities and networks involved, and block public access. This usually needs matching DNS settings so that names resolve to private addresses from the integration runtime and from Azure.
Name resolution
Applications connect by name. After cutover, the new name or address must resolve properly from every client network, including branch offices and report servers. A good trick is to keep applications pointing to a DNS alias, so the final switch is a change of the alias instead of edits in many configuration files.
| Symptom | Likely cause | First check |
|---|---|---|
| Runtime cannot register or connect to Azure | Outbound firewall rule or proxy blocks required addresses | Test outbound HTTPS from the runtime machine |
| Source connection fails | Port closed, wrong credentials or encryption mismatch | Connect from the runtime machine using a normal client |
| Upload is very slow | Shared or throttled link, distant region | Measure real throughput, compare with plan |
| Target cannot read storage | Missing permission or firewall on storage | Check role assignments and network rules |
| Applications cannot reach target after cutover | DNS, route or firewall not prepared | Resolve the name and test the port from the application host |
11Security During a Migration
A migration briefly copies your most valuable data to new places, using powerful temporary access. That is exactly when security is easiest to forget and most important to keep.
Who is allowed to do what
Separate the people who plan a migration from those who hold the data’s secrets. The migration team needs rights to create resources, read the source and write the target, but not necessarily rights to read every row afterward. Use Azure role-based access control to give narrow roles on specific resource groups, and remove them when the project ends. On the databases themselves, create a dedicated migration account with only the permissions the tool documents, rather than reusing an administrator account.
Credentials and secrets
The service and the integration runtime need credentials for the source and the target. Keep these out of documents, chat messages and scripts. Store them in Azure Key Vault, use managed identities where the path supports them, and rotate or delete migration accounts the day after the final cutover. Never let the integration runtime machine become a forgotten place that still holds sign-in details.
Protecting data in transit
Data moves from source to runtime, from runtime to Azure, and inside Azure to the target. Each hop should be encrypted with TLS. Require encrypted connections at the source database where possible, and do not disable certificate checks to make a connection succeed, because that removes the protection you were adding. Use private connections such as ExpressRoute or a VPN for the heaviest transfers.
Protecting data at rest in staging
Backup files in the staging container hold full copies of the database. The storage account must be private, encrypted, restricted to named identities and networks, and monitored. Prefer identity-based access over long-lived keys. If you must use a signed access link, make it short-lived, narrow and read-only for the service, and revoke it at the end. When the migration is finished and verified, delete the staging files and the container, or at least apply a short retention rule.
Encrypted databases and certificates
As noted earlier, databases using transparent data encryption need the matching certificate on the target side before a backup can be restored. Transport it as you would any secret: protected with a strong password, over a trusted channel, and remove copies afterward. Plan the same care for column-level encryption keys, which your application may hold and which must remain available after the move.
Auditing and evidence
Enable audit logging on the source and the target during the project. Keep a record of who ran which migration, when cutover was approved and what was verified. Regulated industries often need this record, and it also helps if a question arises about data that went missing or appeared twice.
| Risk | Control |
|---|---|
| Over-powered migration account | Dedicated account with only the documented permissions, removed after cutover |
| Leaked credentials | Key Vault, managed identities, rotation, no secrets in scripts or chat |
| Interception in transit | TLS everywhere, private network paths, certificate validation on |
| Exposed backup files | Private storage, identity-based access, short retention, delete after verification |
| Lost encryption keys | Secure export and import of certificates, tested restore on a copy |
| Untracked changes | Audit logs, change tickets and a migration journal |
The most common security finding after a migration is left-over access: an open firewall rule, a storage key still in use, a migration account still enabled. Put cleanup on the checklist with an owner and a date.
12Performance and Throughput
Migration speed is rarely limited by the service. It is limited by one of four places: the source, the network, the staging area or the target. Find the slowest and you have found the answer.
The four bottlenecks
Reading from the old server
An aging disk, a busy server or throttled backups can slow every step. Run heavy reads outside peak hours, and avoid starving the live application.
The link to Azure
Bandwidth and delay set the ceiling. Compressed backups send fewer bytes, and parallel uploads help fill a wide link.
Storage and runtime machine
A small runtime machine with slow disks or little memory can be slower than the link. Size it properly.
Writing to the new database
A small target tier throttles restores and bulk loads through log and input and output limits.
Scale the target up for the move
A frequent and cheap trick is to choose a larger target size for the duration of the migration, then scale down afterward. Restores and bulk loads are limited by the performance tier, so extra cores and faster storage shorten the initial load. Because most Azure databases are billed by the hour, a few days at a bigger size cost little compared with the time saved. Remember that scaling operations themselves take time on some services, so do it before the migration starts, not in the middle.
Backups that move faster
For backup-based paths, use compression to shrink files, take backups with checksums as required, and split large backups into several files so they can upload in parallel. Keep log backups small and frequent, so the final one at cutover is short. If the source is busy, schedule the full backup in a quiet period and the log backups on a steady rhythm.
Parallelism in table-copy migrations
Table-copy migrations load several tables at once, and large tables can be split into chunks. Too much parallelism can overload the source or the target, while too little leaves the link idle. Start with the defaults, watch throughput and resource use on both sides, and adjust. Wide tables with large text or binary columns move more slowly than narrow numeric tables, so a few giant tables often define the total time.
Indexes and constraints during load
Loading rows into a table with many indexes is slower, because each index must be updated for each row. In some paths it is helpful to create secondary indexes after the data has loaded. Foreign keys and triggers on the target can also slow loading or cause ordering errors, so many tools turn them off during load and turn them on afterward. Always confirm they are on again before the application starts.
Do not forget statistics
After data arrives in a new database, the engine’s statistics may be missing or stale, and the first queries can run slowly while the optimizer guesses. Update statistics on the target after load, and run the key business queries once before cutover so that caches and plans are warm.
Time a single mid-sized database end to end, record each stage’s speed, and use it to forecast the wave. Estimates built on one real run are far better than those built on vendor numbers.
13Cutover Strategies and Rollback
Cutover is the short moment that decides how the whole project is remembered. A plan that is calm, rehearsed and reversible turns it into an ordinary event.
Three common styles
| Style | How it works | Best for | Risk |
|---|---|---|---|
| Big bang | Stop everything, migrate, switch all applications at once | Small, simple systems | A problem affects everyone; long downtime for large data |
| Phased by database or application | Move one system at a time in waves | Estates with many independent systems | Cross-system dependencies and mixed environments for a while |
| Online with short freeze | Keep the target synchronized, freeze writes briefly, switch | Critical systems that cannot stay offline long | Needs careful rehearsal and monitoring |
The cutover runbook
flowchart TD
A["Confirm lag near zero and health green"] --> B["Announce freeze and stop application writes"]
B --> C["Take final log or capture last changes"]
C --> D["Start cutover in the service"]
D --> E{"Target online and counts match?"}
E -->|"Yes"| F["Switch connection strings or DNS alias"]
F --> G["Run smoke tests and key reports"]
G --> H{"All checks pass?"}
H -->|"Yes"| I["Reopen application and monitor closely"]
H -->|"No"| J["Rollback: point applications back to the source"]
E -->|"No"| J
I --> K["Keep source read only for fallback period"]
Prepare the rollback before you need it
A rollback plan is not a sign of doubt; it is what lets the team make a calm decision. The simplest plan is to keep the source untouched and intact until the target has proven itself. If cutover fails before any new data is written on the target, rollback is just switching the applications back. If the target has already accepted new writes, rolling back means those writes must be copied back, or accepted as lost. For this reason, many teams define a point of no return, a time after which they commit to moving forward and fixing issues on the target.
Reverse replication
For the most critical systems, some teams set up reverse synchronization after cutover, so the old source continues to receive changes from the new target for a while. That makes a late rollback possible without losing data. It adds complexity and is supported only in some paths, so evaluate it carefully and test it in rehearsal.
The cutover window
Choose a time of low activity, with the right people available: the migration lead, a database administrator, an application owner, a network engineer and a business representative who can say yes or no. Write down the schedule minute by minute, and the exact decision that triggers each fallback. Communicate the freeze and the expected duration to users well in advance, and give them a way to ask questions.
Application preparation
Before cutover, the application should already be tested against the target, with new drivers and connection settings tested. Use retry logic for brief connection losses. Use a DNS alias or a central configuration so the switch is one change, not many. Disable scheduled jobs that write to the source at the right moment, and enable the matching jobs on the target only after validation.
A team that has run the cutover three times on a copy, with a stopwatch, knows exactly how long each step takes and what the rollback decision looks like. The real night should feel like the fourth rehearsal.
14Validation and Testing
A migration is finished when the business agrees it works, not when the progress bar turns green. Validation turns “it copied” into “it is correct”.
Levels of checking
Structural checks
Compare the lists of tables, columns, indexes, constraints, views, procedures and permissions between source and target.
Row counts
Compare the number of rows in every table. Differences point to missed or duplicated data and are quick to find.
Content checks
Compare checksums or totals of important columns, such as amounts and dates, and sample individual rows including edge cases.
Behavior checks
Run the same queries, reports and batch jobs against both systems and compare results.
Performance checks
Replay a typical workload and compare response times. Check that the busiest queries use sensible plans.
User acceptance
Let business users run their normal tasks on the new system and sign off in writing.
Counting is not enough
Equal row counts do not prove equal data. A row can be present with a wrong value, a changed character, or a different time zone. Add checks on totals and checksums for critical columns, and compare a random sample of rows with a human eye. In regulated systems, a financial reconciliation, such as comparing the sum of all balances, is a natural check.
Test for what changed
Plan tests around expected differences: collations that sort differently, new default isolation behavior, different handling of dates and decimals, and missing server-level features. A test list built from the assessment report will cover these.
Performance baselines
Before the move, capture a baseline of important queries and their durations on the source. After the move, compare. Slower queries may need an index, an updated statistic, a compatibility level adjustment or a larger target size. A tool that stores query history on the target helps you find regressions quickly.
Keep evidence
Record the validation results, who ran them and the decisions made. This evidence supports the go-live decision, any audit and later troubleshooting.
Orphaned users
Database users with no matching login cannot connect. Test sign-in for every application account.
Identity and sequence values
Auto-numbered columns must continue after the highest existing value, or new inserts will collide.
Jobs and schedules
Every scheduled job must exist, be enabled only on the right side and run successfully once.
Integrations
Connections to other systems, such as file drops and message queues, must point at the new database and work.
15Monitoring, Logging and Troubleshooting
While a migration runs, you need to see its state, its speed and its errors at a glance. Four sources of information cover almost every question.
The migration status view
The Azure portal and the migration tool show each database with a state, such as preparing, restoring the full backup, applying log backups, ready for cutover, cutting over, completed or failed. They also show counts such as how many backup files were found, how many were restored and how many are still pending, plus the last backup applied. For table-copy paths you see tables completed, in progress and in error, with row counts. Learn the meaning of each state before you start.
Activity and diagnostic logs
Azure keeps an activity log of the actions taken on the service resource: who started or stopped a migration and when. Diagnostic settings can send more detailed logs to a Log Analytics workspace, where you can search for errors and build alerts. The integration runtime also keeps its own logs and health pages on its machine, which are the first place to look when it cannot reach the source or Azure.
Source and target database logs
The databases themselves record the other half of the story. On the source, the error log, backup history and replication or binary log status tell you whether changes are available. On the target, restore history, error logs and resource metrics show whether it is throttled or out of space. Many “migration errors” are really database errors surfaced by the service.
Metrics and alerts
Migration failed
Notify the team immediately when any database enters a failed state.
Lag growing
If pending changes keep increasing, the target or the link cannot keep up. Investigate before cutover day.
Target storage near full
A restore or load fails when space runs out. Alert at 80 percent.
Runtime offline
If the helper machine stops reporting, uploads stop silently. Watch its health.
Source log space
If log backups stop, the source log can grow without limit. Alert on log size.
Expiring access
Track the end dates of access tokens and certificates used in the project.
Common errors and their usual causes
| Symptom | Usual cause | What to do |
|---|---|---|
| Cannot connect to source | Credentials, firewall, port, encryption setting | Test from the runtime machine; fix account, rule or certificate trust |
| Backup file not found or not accepted | Wrong container or folder, missing checksum, wrong file type | Check path and naming; retake backup with required options |
| Log chain broken | A log backup was skipped or taken by another tool | Restore the missing file, or restart from a new full backup and keep other backup tools away |
| Restore fails on target | Not enough space, certificate missing, collation or version issue | Increase size, install certificate, review assessment findings |
| Table copy errors | Type not supported, missing key, constraint violation | Fix data or schema on target, then retry the table |
| Lag will not shrink | Heavy writes on source, slow target, narrow link | Scale target, reduce load or improve network, then watch trend |
Write down each error, its cause and its fix. The second database in a wave usually hits the same errors as the first, and a journal turns them into a one-minute fix.
16Understanding the Cost of a Migration
The service itself is only one line on the bill. The real cost of a migration is the sum of many small things, most of which can be planned.
The migration service
Pricing has varied by path and tier, and some paths have no charge for the service. Check the current price page for your scenario.
Target database
You pay for the target from the day it is created, so a long overlap with the source means paying twice.
Staging storage
Backup files cost storage per gigabyte per month, and reading them may involve transactions.
Network
Data coming into Azure is generally free, but ExpressRoute or VPN circuits and gateways cost money.
Runtime machine
The helper machine near the source consumes your own hardware or virtual machine budget.
People and testing
Staff time for assessment, conversion, rehearsal and cutover is usually the largest cost of all.
Ways to keep it down
Create target resources only when the wave is about to start, and size them from real data. Apply Azure Hybrid Benefit if you own eligible SQL Server licenses with Software Assurance, which lowers the compute price of SQL targets. Use reservations for targets that will run steadily after migration. Delete staging files when verification is done. Avoid long parallel-run periods unless the risk justifies them.
A worked overlap example
The numbers below are invented to show the shape. Suppose the target costs 2.10 dollars per hour while running. A three-week overlap for rehearsal, migration, cutover and a fallback period is 21 days times 24 hours, which is 504 hours, so the target costs 2.10 times 504, or about 1,058 dollars. If the team delays cutover by two more weeks, that adds 14 times 24 times 2.10, or about 706 dollars, plus the cost of keeping the old servers. Staging storage for 2 terabytes at an illustrative 0.02 dollars per gigabyte per month is 2,000 times 0.02, or 40 dollars a month. The lesson is that the overlap period and the people involved cost far more than storage, so schedule tightly and finish on time.
The hidden savings and costs
Migration often reveals unused databases, oversized servers and old test copies that can simply be left behind. Retiring those is a real saving. On the other side, a target that is sized too small leads to emergency scaling, and a target sized too large wastes money every month. Review sizing at thirty and ninety days after go-live.
Set a date to switch off the old system, put it in the plan and hold the team to it. Many organizations quietly run both environments for months because nobody owned the shutdown.
17Advantages, Disadvantages and Alternatives
No tool fits every job. Knowing what the service does well, where it struggles and what else exists lets you choose with open eyes.
Advantages
- One managed place to plan, run and watch migrations for many database engines
- Online paths keep downtime to minutes for supported sources and targets
- No migration server software to build and patch inside Azure
- Progress, states and errors are visible in the portal and in logs
- Works with a gradual, wave-based approach across a large estate
- Integrates with assessment and conversion tools in the same ecosystem
Disadvantages
- Support differs by path, so not every source and target pair is covered
- Does not fix incompatible code or redesign a poor schema for you
- Needs a prepared network path and often a helper machine near the source
- Online migration adds overlap cost and needs careful monitoring
- Product features and names change, so documentation must be rechecked
- Some objects, such as jobs and server-level settings, move separately
The main alternatives
| Option | Idea | When it fits |
|---|---|---|
| Native backup and restore | Take a backup, upload it, restore it on the target using engine commands | Same engine, a downtime window is acceptable, and the team knows the commands |
| Native replication or log shipping | Use the engine’s own replication to keep a copy in sync | Same engine and a team with strong database skills |
| Data export and import | Export data to files and load it with bulk tools | Small databases or one-off data moves |
| Data integration pipelines | Copy tables with a general data movement service | Ongoing data flows, transformations, or analytics loads |
| Third-party replication products | Commercial tools for cross-engine change capture | Paths or features the Azure service does not cover |
| Custom code | Write your own migration scripts | Unusual transformations, usually costly to build and test |
How to choose
Start with the simplest option that meets the downtime goal. If a weekend outage is fine and the engine is the same, a plain backup and restore is hard to beat. If the outage must be minutes, or you manage many databases and want consistent visibility, a managed service earns its place. If the engines differ, plan conversion work first, since moving the bytes is the easy part.
Moving house can be done with your own car, a rented van or a professional moving company. For one suitcase, the car is best. For a three-bedroom home with a fixed deadline, the company’s planning, crew and tracking are worth the fee. The migration service is the moving company; backup and restore is the car.
18Design Patterns and Anti-Patterns
Teams that migrate often tend to repeat the same successful habits, and teams that struggle tend to repeat the same mistakes. Naming them makes them easy to copy or avoid.
Patterns that work
Pilot first
Migrate one small, low-risk database end to end before touching important ones. Lessons from the pilot lower the risk of every later wave.
Landing zone
Prepare networks, identity, policies and monitoring in Azure before any data moves, so every migrated database lands in a safe, consistent place.
Assess, convert, test, move
Follow a repeatable pipeline for each database, with a checklist at each gate and clear owners.
Connection indirection
Use DNS aliases or central configuration so applications switch with one change and can switch back just as quickly.
Read-only fallback
Keep the source intact but read-only for a fixed period after cutover, as a safety net and a comparison reference.
Migration factory
For large estates, build a small team with scripts, templates and dashboards so each wave is faster than the last.
Anti-patterns to avoid
Lift and hope
Skipping assessment because the system “looks standard”. Hidden incompatibilities then appear in production.
First rehearsal is the real night
Running cutover for the first time with users waiting. Timing and mistakes are discovered at the worst moment.
Shared admin account
Using one all-powerful login for everything, then leaving it active after the project.
Burn the bridges
Deleting the source on cutover night, leaving no fallback if a hidden problem appears the next morning.
Ignore the application
Moving the database but not testing drivers, connection strings, timeouts and retry behavior in the application.
Forever parallel run
Running old and new together for months with no end date, paying twice and risking split data.
19Best Practices and Common Mistakes
The checklist below distills the lessons of the previous chapters into habits you can apply to any migration project.
Best practices
Inventory everything
List databases, sizes, versions, owners, dependencies and business importance before choosing a method.
Assess early and repeat
Run compatibility and readiness checks at the start and again before each wave, since systems change.
Set targets in writing
Agree on allowed downtime, acceptable data loss and success criteria with the business owner.
Build the network first
Open and test every required path from the runtime machine before the first byte moves.
Rehearse on a copy
Run the full process, including rollback, at least once on realistic data and time it.
Automate repeatable work
Script resource creation, validation and cleanup so each database follows the same path and human error drops.
Communicate often
Tell users the plan, the freeze time and how to report problems, and confirm completion afterward.
Clean up and review
Remove temporary access, delete staging data, update documentation and hold a short lessons-learned meeting.
Common mistakes
| Mistake | Consequence | Prevention |
|---|---|---|
| Untested firewall and DNS | Connections fail on migration day | Test every path from the runtime machine in advance |
| Wrong target size | Slow restore or overspending | Size from measured workload, then adjust after go-live |
| Missing log backups | Broken chain and restarts | Monitor the backup schedule; keep other tools from taking log backups |
| Forgetting logins and jobs | Users cannot sign in; reports do not run | Include server-level objects in the checklist |
| Ignoring collation and time zones | Wrong sorting and shifted timestamps | Compare settings during assessment and test sample data |
| No performance baseline | Cannot tell if the new system is slower | Capture key query timings before the move |
| Leaving access open | Security findings later | Cleanup task with an owner and a date |
| Cutover without a decision owner | Delay and confusion during problems | Name one person who calls go or no-go |
20Failure Scenarios and Recovery
Things will go wrong in some migration, somewhere. A team that has thought through the failures in advance recovers in minutes, not hours.
Scenario one: the network drops during the initial load
The upload from the source to Azure stops halfway. Most paths can resume or restart a file, but a huge single file may need to start again. Prevention is splitting large backups into several files and using a stable, private link. Recovery is checking which files are complete, re-uploading the rest, and confirming file sizes and checksums before the service continues.
Scenario two: the log chain breaks
Someone, or some scheduled job, took a log backup outside the migration process and moved it elsewhere, so a link in the chain is missing. The target cannot proceed. The best recovery is to find the missing file and add it. If it is gone, take a new full backup and start the online migration again. Prevention is to disable competing backup jobs and to limit who can touch the backup schedule.
Scenario three: the target runs out of space
The restore or load fails because the target storage is full, or a temporary workspace fills up. Increase the storage, retry, and review sizing. Prevention is to size the target with growth and temporary space in mind, and to alert at eighty percent used.
Scenario four: cutover validation fails
After the final switch, a key report returns wrong totals. This is the moment the runbook was written for. If the point of no return has not passed, switch the applications back to the source, which is still intact, and investigate in calm conditions. If it has passed, fix the problem on the target using the evidence gathered. Either way, the decision is made by the named owner, based on pre-agreed criteria rather than panic.
Scenario five: the runtime machine fails
The helper machine near the source crashes. Data already in Azure is safe, but new uploads stop. Restart or rebuild the machine, re-register it with the service, and resume. Prevention is to run it on reliable infrastructure, document how to rebuild it, and in critical projects have a second runtime registered as a standby.
Scenario six: the source is too busy
The migration reads place load on the source and users complain. Reduce parallel reads, move heavy steps to quiet hours, and consider reading from a replica or a restored copy of the backup rather than the live server.
flowchart LR
A["Problem detected"] --> B{"Data in target already safe?"}
B -->|"Yes"| C["Fix cause, then resume or retry"]
B -->|"No"| D{"Source still intact?"}
D -->|"Yes"| E["Stop, restart from a new full backup"]
D -->|"No"| F["Restore source from its own backups"]
C --> G["Re-validate counts and checksums"]
E --> G
F --> G
Before any step that cannot be undone, confirm that a verified backup of the source exists in a place the migration cannot touch. This single habit prevents the worst outcomes.
21Real-World Usage Examples
The stories below are typical, invented scenarios. They show how the ideas of this guide combine in practice; they are not reports about any named company.
An online shop leaves its data center lease
A mid-sized shop has a main SQL Server database of 1.2 terabytes and a dozen smaller ones. The lease ends in four months. The team assesses everything, finds two uses of an old feature, rewrites them, and chooses an online backup-based path for the big database and a simple copy for the small ones. They rehearse twice on a copy, schedule cutover on a quiet Tuesday night, and finish in forty minutes of freeze. The old servers stay read-only for two weeks.
A lender moves from a commercial engine to open source
A lender wants to leave a costly license. The migration is heterogeneous: code is converted with an assessment and conversion tool, and about nine percent of the stored procedures need manual rewriting. The team runs old and new in parallel for a month, comparing end-of-day totals every night. After three clean nights in a row, they cut over. The cost savings come from the license, but most project time went into conversion and testing, not data movement.
A clinic network consolidates databases
Several clinics each run their own small database server. The group moves them to a few managed Azure databases in waves of three. Strict privacy rules shape the plan: private network paths, encrypted storage, short-lived access and a signed validation record per clinic. Cutovers happen on Sunday mornings, when appointments are fewest.
A startup moves from self-managed PostgreSQL
A growing startup runs PostgreSQL on a virtual machine that the small team patches and backs up by hand. They move to a managed PostgreSQL service using logical replication to keep the target current. Downtime is under two minutes. Sequences are reset after cutover, a step the team nearly forgot because the checklist from the pilot reminded them.
An agency retires an old mainframe-adjacent system
An agency has a decades-old database with unusual character encodings. Early tests show scrambled names. The team spends weeks on character set mapping and builds a validation script comparing every name field before they move a single production row. The slow, careful start saves them from a painful public failure.
What these stories share
None of them were saved by clever tools alone. Each succeeded through early assessment, realistic rehearsal, clear ownership, honest validation and a way back. The service handled copying; the team handled everything that mattered.
22Frequently Asked Questions
Short answers to the questions that come up most often. Where a detail may have changed, check the current Microsoft documentation.
23Summary and Key Takeaways
A database migration is a careful move of something valuable. The service gives you a managed, visible way to do the copying; your plan gives you the safety.
Key takeaways
- The service is a mover, not a storage place: it copies schema and data from a source to a target, offline or online, and shows you the progress.
- Success depends on assessment, conversion and planning more than on the copy itself, especially when changing database engines.
- Choose the path from your downtime goal, engine pair and data size; the simplest method that meets the goal is usually best.
- Prepare the network, identity and security first, and clean up temporary access and staging data afterward.
- Rehearse cutover on a copy, define a point of no return and keep the source intact as a fallback.
- Validate beyond row counts: compare checksums, run business reports, test logins, jobs and performance against a baseline.
- Check current Microsoft documentation for supported paths, limits and prices, since these change over time.