{"id":483,"date":"2026-04-14T05:19:03","date_gmt":"2026-04-14T05:19:03","guid":{"rendered":"https:\/\/www.devopsschool.com\/tutorials\/azure-database-migration-service-tutorial-architecture-pricing-use-cases-and-hands-on-guide-for-migration\/"},"modified":"2026-04-14T05:19:03","modified_gmt":"2026-04-14T05:19:03","slug":"azure-database-migration-service-tutorial-architecture-pricing-use-cases-and-hands-on-guide-for-migration","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/tutorials\/azure-database-migration-service-tutorial-architecture-pricing-use-cases-and-hands-on-guide-for-migration\/","title":{"rendered":"Azure Database Migration Service Tutorial: Architecture, Pricing, Use Cases, and Hands-On Guide for Migration"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Category<\/h2>\n\n\n\n<p>Migration<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction<\/h2>\n\n\n\n<p>Azure Database Migration Service is Microsoft\u2019s managed migration orchestration service for moving databases from on-premises, virtual machines, and other clouds into Azure data platforms. It helps you plan and execute database migrations with structured projects, guided workflows, and progress tracking.<\/p>\n\n\n\n<p>In simple terms: <strong>you create a migration service in Azure, connect it to a source database and a target Azure database, then run a migration job<\/strong> (offline or online, depending on the scenario). You monitor progress and validate that the target is ready for cutover.<\/p>\n\n\n\n<p>Technically, Azure Database Migration Service provides a <strong>managed \u201cmigration runtime\u201d hosted in Azure<\/strong> that connects to source\/target endpoints over the network, performs schema and\/or data movement depending on the migration type, and reports status back to the Azure control plane (Azure Portal\/ARM). It\u2019s typically deployed into an <strong>Azure virtual network (VNet)<\/strong> so it can securely reach private source systems.<\/p>\n\n\n\n<p>The main problem it solves is that real migrations are rarely just \u201cexport\/import.\u201d Teams need repeatable steps, secure connectivity, minimal downtime options, and reliable status reporting. Azure Database Migration Service provides a structured way to move databases into Azure while reducing risk and manual effort.<\/p>\n\n\n\n<blockquote>\n<p>Important note on current positioning: Microsoft also provides newer guided experiences for some migrations (for example, <strong>Azure SQL migration<\/strong> experiences in Azure tools\/portals). In some cases, those experiences may use Azure Database Migration Service under the hood or may be the preferred workflow for specific sources\/targets. <strong>Always confirm the current recommended approach and support matrix in official documentation<\/strong> before you commit to a tooling path.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">2. What is Azure Database Migration Service?<\/h2>\n\n\n\n<p><strong>Official purpose (what it\u2019s for):<\/strong><br\/>\nAzure Database Migration Service is designed to <strong>enable database migrations to Azure<\/strong> by providing a managed service that coordinates and executes migration tasks. It supports a range of source engines and Azure targets, with capabilities that vary by migration scenario.<\/p>\n\n\n\n<p><strong>Core capabilities (high level):<\/strong>\n&#8211; Create <strong>migration projects<\/strong> and run <strong>migration activities\/jobs<\/strong>\n&#8211; Support for <strong>offline migrations<\/strong> (cutover requires downtime) and <strong>online migrations<\/strong> (reduced downtime) for certain engines\/targets\n&#8211; Guided selection of <strong>source\/target types<\/strong> and migration modes\n&#8211; Progress monitoring, basic error reporting, and orchestration support for iterative migration work<\/p>\n\n\n\n<p><strong>Major components:<\/strong>\n&#8211; <strong>Azure Database Migration Service resource<\/strong>: The service instance you deploy in a subscription\/resource group, usually into a VNet subnet.\n&#8211; <strong>Migration project<\/strong>: A logical container where you choose source\/target types and organize migration activities.\n&#8211; <strong>Migration activities\/tasks<\/strong>: The operations that move schema\/data (depending on scenario) and track progress.\n&#8211; <strong>Networking dependencies<\/strong>: VNet\/subnet placement, DNS, routing, NSGs, VPN\/ExpressRoute, firewall rules\u2014these often determine whether migrations succeed.<\/p>\n\n\n\n<p><strong>Service type:<\/strong><br\/>\nA managed Azure service (PaaS-style control plane), typically deployed into your network boundary to reach private endpoints.<\/p>\n\n\n\n<p><strong>Scope (regional\/subscription\/resource group):<\/strong>\n&#8211; You create Azure Database Migration Service as an <strong>Azure resource in a specific region<\/strong>.\n&#8211; It lives in a <strong>subscription<\/strong> and <strong>resource group<\/strong>.\n&#8211; For most non-trivial scenarios, it is associated with an <strong>Azure VNet\/subnet<\/strong> in that region (regional resource with regional networking).<\/p>\n\n\n\n<p><strong>How it fits into the Azure ecosystem:<\/strong>\n&#8211; Works alongside assessment and readiness tooling such as:\n  &#8211; <strong>Azure Migrate<\/strong> (discovery\/assessment at a broader level)\n  &#8211; Database-specific assessment tools (for example, SQL assessment tools).<br\/>\n  Exact tooling depends on engine and target\u2014<strong>verify in official docs<\/strong>.\n&#8211; Pairs with Azure database targets such as:\n  &#8211; <strong>Azure SQL Database<\/strong>\n  &#8211; <strong>Azure SQL Managed Instance<\/strong>\n  &#8211; <strong>Azure Database for PostgreSQL<\/strong>\n  &#8211; <strong>Azure Database for MySQL<\/strong>\n  &#8211; Other supported targets as listed in Microsoft\u2019s support matrix (varies over time\u2014verify)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Why use Azure Database Migration Service?<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Business reasons<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Reduce migration risk<\/strong> with a guided process and predictable stages.<\/li>\n<li><strong>Shorten project timelines<\/strong> compared to building custom migration pipelines.<\/li>\n<li><strong>Support modernization<\/strong> by moving from self-managed databases to managed Azure services.<\/li>\n<li><strong>Enable phased cutovers<\/strong> and rehearsal migrations (especially valuable for regulated environments).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Technical reasons<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Supports structured migration workflows (offline\/online depending on scenario).<\/li>\n<li>Works in <strong>private networking<\/strong> contexts (VNet-integrated), which is common for production databases.<\/li>\n<li>Provides a central Azure-native place to manage migration activities and status.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Operational reasons<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Repeatable migrations across environments (dev\/test\/prod) with clearer orchestration than ad-hoc scripts.<\/li>\n<li>Monitoring via portal-based status and error views; integrates with standard Azure governance patterns (tags, RBAC, resource groups).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Security\/compliance reasons<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Can be deployed into a <strong>private subnet<\/strong> and connected over <strong>VPN\/ExpressRoute<\/strong> to keep traffic off the public internet.<\/li>\n<li>Leverages Azure RBAC for access to the migration service resource.<\/li>\n<li>Helps implement separation of duties (migration operators vs. target platform admins).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Scalability\/performance reasons<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Offloads migration execution into a managed service that can be sized\/selected via service tier options (exact tiers and capabilities vary\u2014verify in pricing\/docs).<\/li>\n<li>Supports parallelization patterns in some scenarios (for example, migrating multiple databases or tables), subject to service and target constraints.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">When teams should choose it<\/h3>\n\n\n\n<p>Choose Azure Database Migration Service when:\n&#8211; You need a <strong>guided, Azure-supported<\/strong> migration path.\n&#8211; You require <strong>VNet-based connectivity<\/strong> to private sources.\n&#8211; You want <strong>online (reduced downtime)<\/strong> migration where supported.\n&#8211; You want a migration approach that fits Azure governance and enterprise controls.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">When teams should not choose it<\/h3>\n\n\n\n<p>Avoid or reconsider Azure Database Migration Service when:\n&#8211; Your migration is a simple one-time export\/import and you already have safe, tested scripts.\n&#8211; Your source\/target pair is <strong>not supported<\/strong> or your required migration mode (online\/offline) isn\u2019t available for that pair.\n&#8211; Your biggest issues are <strong>application refactoring<\/strong>, not data movement (you may need app modernization work first).\n&#8211; You can use a more specialized or recommended workflow (for example, a database-specific migration toolchain) that better matches your target architecture\u2014<strong>verify current recommendations<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Where is Azure Database Migration Service used?<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Industries<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Finance and insurance (controlled change windows, audit needs)<\/li>\n<li>Healthcare (regulated data handling, strict network boundaries)<\/li>\n<li>Retail\/e-commerce (minimize downtime, scale managed services)<\/li>\n<li>Manufacturing\/IoT (legacy databases in plants moving to cloud)<\/li>\n<li>Government (private connectivity, compliance-driven migrations)<\/li>\n<li>SaaS providers (consolidating customer databases onto managed platforms)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Team types<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Platform engineering teams building standardized migration runbooks<\/li>\n<li>Database administrators (DBAs) leading migration execution<\/li>\n<li>Cloud center of excellence (CCoE) defining migration patterns<\/li>\n<li>DevOps\/SRE teams responsible for reliability and cutover operations<\/li>\n<li>Security engineers reviewing network and identity controls<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Workloads<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Line-of-business apps backed by SQL databases<\/li>\n<li>Reporting databases migrating to Azure-managed database platforms<\/li>\n<li>Multi-tenant SaaS databases consolidating or replatforming<\/li>\n<li>Legacy on-premises SQL\/MySQL\/PostgreSQL environments moving to Azure<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Architectures<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Hub-and-spoke networking with shared services VNets<\/li>\n<li>Hybrid networks (on-prem to Azure via VPN\/ExpressRoute)<\/li>\n<li>Landing zone deployments where migrations must follow tagging, RBAC, and policy controls<\/li>\n<li>Blue\/green cutover patterns for applications<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Real-world deployment contexts<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Production migrations<\/strong> with carefully controlled cutover windows and rollback plans<\/li>\n<li><strong>Dev\/test migrations<\/strong> for modernization testing and performance validation<\/li>\n<li><strong>Disaster recovery migrations<\/strong> (less common, but sometimes used to seed data into Azure)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">5. Top Use Cases and Scenarios<\/h2>\n\n\n\n<p>Below are realistic scenarios where Azure Database Migration Service is commonly used. Each includes the problem, why the service fits, and an example.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) SQL Server to Azure SQL Database (offline)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Move a SQL Server database to Azure SQL Database with a planned downtime window.<\/li>\n<li><strong>Why it fits:<\/strong> Provides a guided workflow and status tracking for moving data into Azure SQL Database.<\/li>\n<li><strong>Example:<\/strong> A departmental app migrates from a SQL Server VM to Azure SQL Database over a weekend maintenance window.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2) SQL Server to Azure SQL Managed Instance (replatform with reduced downtime where supported)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Maintain high compatibility with SQL Server features while reducing downtime.<\/li>\n<li><strong>Why it fits:<\/strong> Online\/reduced-downtime patterns may be supported depending on versions and configuration (verify).<\/li>\n<li><strong>Example:<\/strong> A CRM database uses SQL Agent and cross-database features; team chooses Azure SQL Managed Instance and runs a minimized downtime cutover.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3) MySQL to Azure Database for MySQL (replatform)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Replace self-managed MySQL with managed MySQL in Azure.<\/li>\n<li><strong>Why it fits:<\/strong> Orchestrates schema\/data movement (scenario-dependent) with centralized management.<\/li>\n<li><strong>Example:<\/strong> A LAMP stack uses MySQL on a Linux VM; team migrates to Azure Database for MySQL for patching\/backup automation.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4) PostgreSQL to Azure Database for PostgreSQL (migration with replication-based cutover where supported)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Minimize downtime while moving a PostgreSQL database.<\/li>\n<li><strong>Why it fits:<\/strong> Some PostgreSQL migrations can use online methods (verify exact requirements).<\/li>\n<li><strong>Example:<\/strong> A fintech service migrates from on-prem PostgreSQL to Azure Database for PostgreSQL during a short cutover.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5) Oracle to Azure (engine-specific pathways)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Leave expensive on-prem licensing and hardware while retaining database capabilities.<\/li>\n<li><strong>Why it fits:<\/strong> Azure migration pathways exist, but Oracle migrations can be complex and may require additional tooling (verify current best practice).<\/li>\n<li><strong>Example:<\/strong> An enterprise ERP system migrates Oracle databases to Azure targets with a combination of tools and staged cutover.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">6) Hybrid migrations over VPN\/ExpressRoute<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Source database cannot be exposed to the internet.<\/li>\n<li><strong>Why it fits:<\/strong> Deploy Azure Database Migration Service into a VNet and route privately to on-prem networks.<\/li>\n<li><strong>Example:<\/strong> A hospital migrates a patient system database over ExpressRoute, keeping all traffic private.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">7) Multi-database wave migrations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Hundreds of small databases need standardized migration execution.<\/li>\n<li><strong>Why it fits:<\/strong> Projects and activities create consistent operational workflows and auditing.<\/li>\n<li><strong>Example:<\/strong> A SaaS provider moves per-customer databases in waves, tracking each migration and cutover.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">8) Pre-production rehearsal and cutover validation<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Need repeatable rehearsals to validate downtime, performance, and rollback.<\/li>\n<li><strong>Why it fits:<\/strong> Enables structured runs and iteration (even if you recreate the target each time).<\/li>\n<li><strong>Example:<\/strong> Team runs three rehearsal migrations to refine timing and confirm the application works with the Azure target.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">9) Consolidation into fewer managed instances\/databases<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Reduce operational overhead by consolidating multiple on-prem databases into Azure-managed services.<\/li>\n<li><strong>Why it fits:<\/strong> Supports a controlled migration plan with staged moves.<\/li>\n<li><strong>Example:<\/strong> Ten on-prem SQL Server databases move into a smaller number of Azure SQL Managed Instances.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">10) Data center exit deadlines<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Fixed deadline to vacate a data center; migrations must be executed reliably and tracked.<\/li>\n<li><strong>Why it fits:<\/strong> Provides a standardized, Azure-native migration execution approach.<\/li>\n<li><strong>Example:<\/strong> A retailer uses an Azure landing zone, then migrates databases in prioritized order with traceable migration status.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">11) Split production and reporting workloads<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Reporting workload overloads production database.<\/li>\n<li><strong>Why it fits:<\/strong> Migration can move the reporting database to Azure as a first step, then production later.<\/li>\n<li><strong>Example:<\/strong> Move a replicated reporting database to Azure SQL first, then plan the OLTP migration.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">12) Regulated change control with evidence<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> Need evidence of steps, timing, and validation for audits.<\/li>\n<li><strong>Why it fits:<\/strong> Projects\/activities plus Azure Activity Log and operational runbooks support audit trails.<\/li>\n<li><strong>Example:<\/strong> A bank runs migrations under change tickets, capturing configurations, results, and validation queries.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">6. Core Features<\/h2>\n\n\n\n<blockquote>\n<p>Feature availability depends on the <strong>source engine, target engine, versions, and chosen migration mode<\/strong>. Always validate your exact scenario against Microsoft\u2019s official support matrix.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">1) Migration projects and guided workflows<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Organizes migrations by source\/target type and provides guided steps to configure endpoints and run activities.<\/li>\n<li><strong>Why it matters:<\/strong> Reduces missed steps and provides consistency across migrations.<\/li>\n<li><strong>Practical benefit:<\/strong> Faster onboarding for new operators; repeatable execution.<\/li>\n<li><strong>Caveats:<\/strong> UI and available project types change over time\u2014verify the latest portal\/tooling flow in official docs.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2) Offline migrations (planned downtime)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Moves data in a batch; applications are typically stopped during final cutover to avoid data changes.<\/li>\n<li><strong>Why it matters:<\/strong> Simplest and often most reliable migration mode.<\/li>\n<li><strong>Practical benefit:<\/strong> Predictable run steps; fewer moving parts than continuous replication.<\/li>\n<li><strong>Caveats:<\/strong> Requires downtime window; large databases can exceed the window without careful planning.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3) Online (reduced downtime) migrations (scenario-dependent)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Uses continuous synchronization patterns to reduce cutover downtime.<\/li>\n<li><strong>Why it matters:<\/strong> Enables near-zero or reduced downtime migrations for critical systems.<\/li>\n<li><strong>Practical benefit:<\/strong> Shorter outages; business continuity.<\/li>\n<li><strong>Caveats:<\/strong> Not supported for every source\/target; may have prerequisites (replication settings, log retention, permissions). Verify exact requirements.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4) VNet-integrated deployment for private connectivity<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Deploys the service into your VNet subnet so it can reach private IPs for source systems.<\/li>\n<li><strong>Why it matters:<\/strong> Production databases are commonly private; public exposure is often prohibited.<\/li>\n<li><strong>Practical benefit:<\/strong> Works with VPN\/ExpressRoute; aligns with enterprise security.<\/li>\n<li><strong>Caveats:<\/strong> Subnet sizing and NSG rules are common failure points; plan networking early.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5) Status monitoring and progress tracking<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Shows progress of migration activities, including errors and completion status.<\/li>\n<li><strong>Why it matters:<\/strong> Operators need visibility and ability to troubleshoot quickly.<\/li>\n<li><strong>Practical benefit:<\/strong> Easier coordination during cutover windows.<\/li>\n<li><strong>Caveats:<\/strong> Depth of logs\/metrics can vary; for deep troubleshooting you may still need source\/target engine logs.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">6) Integration with Azure governance (RBAC, tags, resource groups)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Uses standard Azure resource management controls.<\/li>\n<li><strong>Why it matters:<\/strong> Enterprises need consistent access controls and cost allocation.<\/li>\n<li><strong>Practical benefit:<\/strong> Least privilege access and chargeback\/showback.<\/li>\n<li><strong>Caveats:<\/strong> RBAC controls access to the service resource; it does not automatically grant database-level permissions on source\/target.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">7) Support for multiple database engines and Azure targets (via support matrix)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>What it does:<\/strong> Provides a single Azure-native service for multiple migration types.<\/li>\n<li><strong>Why it matters:<\/strong> Standardization reduces tool sprawl.<\/li>\n<li><strong>Practical benefit:<\/strong> Shared runbooks and operational patterns.<\/li>\n<li><strong>Caveats:<\/strong> Capability differences across engines are significant; validate per engine.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">7. Architecture and How It Works<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">High-level architecture<\/h3>\n\n\n\n<p>Azure Database Migration Service consists of:\n&#8211; A <strong>control plane<\/strong>: Azure Resource Manager + Azure Portal (and sometimes other Microsoft tools) to create\/manage the DMS resource and migration projects.\n&#8211; A <strong>data plane<\/strong>: The migration runtime deployed into your VNet that connects to source\/target endpoints and transfers data.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Request\/data\/control flow (typical)<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>You create Azure Database Migration Service in Azure (control plane operation).<\/li>\n<li>You create a migration project and activity in the portal (control plane).<\/li>\n<li>The DMS runtime connects to:\n   &#8211; <strong>Source database<\/strong> (often private IP reachable through VNet routing\/VPN\/ExpressRoute)\n   &#8211; <strong>Target Azure database<\/strong> (public endpoint with firewall rules or private endpoint)<\/li>\n<li>Data is moved according to the selected mode.<\/li>\n<li>DMS reports status back to the portal.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Integrations with related services<\/h3>\n\n\n\n<p>Common integrations (not all are required):\n&#8211; <strong>Azure Virtual Network<\/strong>: Required for many scenarios so DMS can reach private sources.\n&#8211; <strong>Azure VPN Gateway \/ ExpressRoute<\/strong>: For hybrid connectivity to on-prem sources.\n&#8211; <strong>Azure SQL \/ Azure Database for PostgreSQL\/MySQL<\/strong>: Targets.\n&#8211; <strong>Azure Storage<\/strong>: Sometimes used in migration workflows (for example, backup files), depending on scenario\u2014verify.\n&#8211; <strong>Azure Monitor \/ Activity Log<\/strong>: Operational governance around resource changes; deeper telemetry varies\u2014verify.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Dependency services<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DNS resolution between DMS subnet and source\/target endpoints<\/li>\n<li>Network routing (UDRs, VPN\/ER routes)<\/li>\n<li>Firewalls\/NSGs<\/li>\n<li>Database engine permissions on source and target<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Security\/authentication model<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Azure RBAC<\/strong> controls who can create\/manage the DMS resource and migration projects.<\/li>\n<li><strong>Database authentication<\/strong> to source\/target typically uses database credentials you provide (SQL logins, database users, etc.).<\/li>\n<li>Where Azure AD authentication is an option (for example, Azure SQL), DMS support depends on the scenario\u2014<strong>verify in official docs<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Networking model<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DMS is commonly deployed into a <strong>dedicated subnet<\/strong>.<\/li>\n<li>It must have IP connectivity to:<\/li>\n<li>Source database host\/port<\/li>\n<li>Target database host\/port<\/li>\n<li>Targets may be accessed via:<\/li>\n<li>Public endpoint + firewall rules (and sometimes \u201cAllow Azure services\u2026\u201d style settings for Azure SQL)<\/li>\n<li>Private endpoint (requires private DNS + VNet integration)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Monitoring\/logging\/governance considerations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>resource tags<\/strong> and naming conventions for traceability.<\/li>\n<li>Track operator activity via <strong>Azure Activity Log<\/strong> (who created\/modified the service\/projects).<\/li>\n<li>Capture migration run logs\/status screenshots\/exports as part of change management evidence (where required).<\/li>\n<li>For performance and errors, also monitor <strong>source\/target engine logs and metrics<\/strong> (DTU\/vCore utilization, locks, replication lag, storage IOPS, etc.).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Simple architecture diagram (Mermaid)<\/h3>\n\n\n\n<pre><code class=\"language-mermaid\">flowchart LR\n  U[Operator] --&gt; P[Azure Portal \/ ARM]\n  P --&gt; DMS[Azure Database Migration Service&lt;br\/&gt;in Azure VNet subnet]\n  DMS --&gt; SRC[Source DB&lt;br\/&gt;SQL Server on VM\/on-prem]\n  DMS --&gt; TGT[Target DB&lt;br\/&gt;Azure SQL Database]\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Production-style architecture diagram (Mermaid)<\/h3>\n\n\n\n<pre><code class=\"language-mermaid\">flowchart TB\n  subgraph OnPrem[On-premises \/ Legacy environment]\n    SRCDB[(Source Database)]\n    APP[Application Servers]\n  end\n\n  subgraph Azure[Azure Subscription]\n    subgraph Hub[Hub VNet]\n      VPN[VPN\/ExpressRoute Gateway]\n      DNS[DNS \/ Private Resolver (optional)]\n    end\n\n    subgraph Spoke[Spoke VNet - Migration]\n      subgraph Subnets[Subnets]\n        DMSNET[Dedicated DMS Subnet]\n        MGMT[Ops\/Bastion Subnet (optional)]\n      end\n      DMS[Azure Database Migration Service]\n      BASTION[Azure Bastion (optional)]\n      JUMP[Jumpbox\/VM for tools (optional)]\n    end\n\n    subgraph Data[Azure Data Platform]\n      AZSQL[(Azure SQL Database \/ Managed Instance)]\n      KV[Key Vault (recommended for secrets mgmt)]\n      MON[Azure Monitor \/ Log Analytics (verify DMS telemetry options)]\n    end\n  end\n\n  APP --&gt; SRCDB\n  SRCDB &lt;--&gt;|Private routes| VPN\n  VPN &lt;--&gt;|VNet peering \/ routing| Spoke\n  DMS --&gt;|DB port| SRCDB\n  DMS --&gt;|DB port| AZSQL\n  U[Admins\/Operators] --&gt; BASTION --&gt; JUMP\n  JUMP --&gt; SRCDB\n  JUMP --&gt; AZSQL\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8. Prerequisites<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Azure account\/subscription requirements<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>An active <strong>Azure subscription<\/strong> with permission to create:<\/li>\n<li>Resource groups<\/li>\n<li>Virtual networks\/subnets<\/li>\n<li>Azure Database Migration Service resource<\/li>\n<li>Target database service (Azure SQL, etc.)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Permissions \/ IAM roles (typical)<\/h3>\n\n\n\n<p>Exact role needs vary by org policy; common minimums:\n&#8211; <strong>Contributor<\/strong> on the resource group (to create resources), or more restrictive custom roles:\n  &#8211; Ability to create\/manage DMS\n  &#8211; Ability to create\/manage VNet\/subnet resources (or have networking team do it)\n  &#8211; Ability to create\/manage Azure SQL resources (or have DBA\/platform team do it)\n&#8211; Database-level permissions:\n  &#8211; On <strong>source<\/strong>: privileges sufficient to read schema\/data and, for online migrations, replication\/log access (scenario-dependent)\n  &#8211; On <strong>target<\/strong>: privileges to create schema\/objects and write data<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Billing requirements<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DMS service tier charges (usage-based)<\/li>\n<li>Target database charges (Azure SQL)<\/li>\n<li>VM charges if you host a source database in Azure for testing<\/li>\n<li>Networking charges if using VPN\/ExpressRoute<\/li>\n<li>Storage charges for backups\/logs if used<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Tools needed (for this tutorial)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Azure Portal access<\/li>\n<li>Azure CLI (optional but recommended): https:\/\/learn.microsoft.com\/cli\/azure\/install-azure-cli<\/li>\n<li>SQL client for validation:<\/li>\n<li><code>sqlcmd<\/code> (for SQL Server\/Azure SQL) or Azure Data Studio\/SSMS on your workstation<\/li>\n<li>In this lab we\u2019ll use <code>sqlcmd<\/code> on a Linux VM for repeatability<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Region availability<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Azure Database Migration Service is a <strong>regional<\/strong> service.<\/li>\n<li>Not every region supports every combination or feature. <strong>Verify region support in official docs<\/strong> before choosing a region.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Quotas\/limits<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Subnet sizing and service constraints can block deployment.<\/li>\n<li>Migration throughput depends on service tier, network bandwidth\/latency, and target performance tier.<\/li>\n<li>Always review DMS limits and constraints in official docs for your migration type.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Prerequisite services (for typical hybrid production)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Azure VNet + dedicated subnet for DMS<\/li>\n<li>VPN Gateway or ExpressRoute (if source is on-prem and private)<\/li>\n<li>Target database provisioned and reachable from DMS<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">9. Pricing \/ Cost<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Current pricing model (how you are charged)<\/h3>\n\n\n\n<p>Azure Database Migration Service pricing is primarily based on:\n&#8211; <strong>Selected service tier\/SKU<\/strong> (for example, tiers that may differentiate offline vs online capability)\n&#8211; <strong>Compute\/time<\/strong> the migration service runs (billing often correlates with hours the service is provisioned or actively running\u2014confirm exact billing rules on the pricing page)\n&#8211; Potentially other SKU dimensions (region-dependent)<\/p>\n\n\n\n<p>Because pricing changes and is region-dependent, <strong>do not rely on blog posts for numbers<\/strong>. Use:\n&#8211; Official pricing page: https:\/\/azure.microsoft.com\/pricing\/details\/database-migration\/\n&#8211; Azure Pricing Calculator: https:\/\/azure.microsoft.com\/pricing\/calculator\/<\/p>\n\n\n\n<blockquote>\n<p>Verify the current tier names and exactly what is billed (provisioned hours vs active hours) in the official pricing page. The model has changed over time.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Pricing dimensions to plan for<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DMS service tier<\/strong> (capabilities and performance)<\/li>\n<li><strong>Runtime duration<\/strong> (hours\/days the service exists and\/or runs migrations)<\/li>\n<li><strong>Data volume<\/strong> migrated and how many attempts\/rehearsals you run<\/li>\n<li><strong>Network path<\/strong> (VPN\/ExpressRoute vs in-Azure)<\/li>\n<li><strong>Target database sizing<\/strong> (Azure SQL tier\/vCores\/storage)<\/li>\n<li><strong>Source environment costs<\/strong> (VMs, storage, licenses) if you run migration staging in Azure<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Free tier<\/h3>\n\n\n\n<p>Azure Database Migration Service has historically had limited-time or scenario-specific considerations; <strong>assume no free tier<\/strong> unless explicitly stated on the official pricing page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Key cost drivers (direct + indirect)<\/h3>\n\n\n\n<p><strong>Direct:<\/strong>\n&#8211; DMS tier + hours\n&#8211; Target database compute\/storage (often the dominant cost in production)<\/p>\n\n\n\n<p><strong>Indirect\/hidden:<\/strong>\n&#8211; <strong>Rehearsal migrations<\/strong> (multiple runs multiply compute\/time)\n&#8211; <strong>Network egress<\/strong> from on-prem or other clouds (ISP\/MPLS costs, cloud egress)\n&#8211; <strong>VPN Gateway \/ ExpressRoute<\/strong> hourly + data processing costs\n&#8211; <strong>Operational time<\/strong>: troubleshooting connectivity, performance tuning, and validation\n&#8211; <strong>Downtime cost<\/strong>: offline migrations can have business impact<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Network\/data transfer implications<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Data movement <strong>within Azure<\/strong> is typically cheaper than cross-cloud.<\/li>\n<li>Moving data <strong>out of other clouds<\/strong> usually incurs significant egress fees.<\/li>\n<li>Hybrid migrations depend on your network throughput\/latency; slow links increase migration duration (and therefore cost).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">How to optimize cost<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Prefer <strong>offline migrations<\/strong> for non-critical workloads when downtime is acceptable.<\/li>\n<li>Run <strong>rehearsals<\/strong> on smaller subsets or restored copies to validate steps before full runs.<\/li>\n<li>Right-size:<\/li>\n<li>DMS tier (don\u2019t overpay for features you can\u2019t use)<\/li>\n<li>Target database tier during migration (you may temporarily scale up for load, then scale down)<\/li>\n<li>Keep the service alive only as long as needed; delete resources after migration if not required.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Example low-cost starter estimate (model, not numbers)<\/h3>\n\n\n\n<p>A low-cost lab typically includes:\n&#8211; 1 small Linux VM (B-series) for a source SQL Server test instance\n&#8211; 1 small Azure SQL Database for target\n&#8211; 1 Azure Database Migration Service instance (lowest tier that supports your scenario)\n&#8211; Minimal networking (single VNet)<\/p>\n\n\n\n<p>Total cost depends on:\n&#8211; Region\n&#8211; VM hours\n&#8211; Azure SQL tier and storage\n&#8211; DMS tier and hours<br\/>\nUse the Azure Pricing Calculator to model these components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Example production cost considerations<\/h3>\n\n\n\n<p>For production, plan for:\n&#8211; Separate environments (dev\/test\/prod) and at least one rehearsal = multiple runs\n&#8211; Higher Azure SQL tiers during migration windows\n&#8211; VPN\/ExpressRoute costs if hybrid\n&#8211; Operational overhead for monitoring, cutover support, rollback readiness\n&#8211; Data validation tooling and potential parallel run periods<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">10. Step-by-Step Hands-On Tutorial<\/h2>\n\n\n\n<p>This lab demonstrates an <strong>offline migration of SQL Server to Azure SQL Database<\/strong> using <strong>Azure Database Migration Service<\/strong>. The source SQL Server runs on a small Linux VM in Azure to keep networking simple and costs controllable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Objective<\/h3>\n\n\n\n<p>Migrate a sample SQL Server database from a SQL Server instance running on an Ubuntu VM to <strong>Azure SQL Database<\/strong> using <strong>Azure Database Migration Service (offline migration)<\/strong>, then validate data and clean up resources.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Lab Overview<\/h3>\n\n\n\n<p>You will:\n1. Create a resource group and virtual network with two subnets (VM + DMS).\n2. Deploy an Ubuntu VM and install SQL Server Developer Edition.\n3. Create a sample database and data on the source SQL Server.\n4. Create an Azure SQL Database target.\n5. Deploy Azure Database Migration Service into a dedicated subnet.\n6. Create a migration project and run an offline migration.\n7. Validate row counts on the target.\n8. Clean up all resources.<\/p>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nYou can log into Azure SQL Database and query the migrated tables with matching row counts.<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Create the Azure resource group, VNet, and subnets<\/h3>\n\n\n\n<p><strong>Why:<\/strong> DMS commonly requires VNet integration, and you want the DMS runtime to reach the source SQL Server privately.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In Azure Portal, create a <strong>Resource group<\/strong> (example: <code>rg-dms-lab<\/code>).<\/li>\n<li>Create a <strong>Virtual network<\/strong> (example: <code>vnet-dms-lab<\/code>) in the same region.<\/li>\n<\/ol>\n\n\n\n<p>Create two subnets:\n&#8211; <code>subnet-vm<\/code> (example: <code>10.10.1.0\/24<\/code>)\n&#8211; <code>subnet-dms<\/code> (example: <code>10.10.2.0\/27<\/code>)<\/p>\n\n\n\n<blockquote>\n<p>DMS subnet sizing requirements can be strict (often requiring at least <code>\/27<\/code> and dedicated use). <strong>Verify current subnet requirements in official docs<\/strong> if deployment fails.<\/p>\n<\/blockquote>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nA VNet with two subnets exists.<\/p>\n\n\n\n<p><strong>Verification:<\/strong>\n&#8211; Azure Portal \u2192 Virtual networks \u2192 <code>vnet-dms-lab<\/code> \u2192 Subnets shows both subnets.<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Deploy an Ubuntu VM for the source SQL Server<\/h3>\n\n\n\n<p><strong>Why:<\/strong> You need a source database endpoint accessible to DMS over the network.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create an <strong>Ubuntu LTS<\/strong> VM (example size: <code>Standard_B2s<\/code>) in <code>subnet-vm<\/code>.<\/li>\n<li>Allow inbound:\n   &#8211; SSH (22) from your public IP (for admin access)<\/li>\n<li>Do <strong>not<\/strong> expose SQL Server (1433) to the internet.<\/li>\n<\/ol>\n\n\n\n<p><strong>NSG rule for SQL Server (internal only):<\/strong>\n&#8211; Inbound rule on VM\u2019s NSG:\n  &#8211; Source: <code>10.10.2.0\/27<\/code> (the DMS subnet)\n  &#8211; Destination port: <code>1433<\/code>\n  &#8211; Protocol: TCP\n  &#8211; Action: Allow<\/p>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nVM is reachable via SSH, and port 1433 is reachable from the DMS subnet only.<\/p>\n\n\n\n<p><strong>Verification (SSH):<\/strong>\nFrom your workstation:<\/p>\n\n\n\n<pre><code class=\"language-bash\">ssh azureuser@&lt;VM_PUBLIC_IP&gt;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Install SQL Server on Ubuntu and create sample data<\/h3>\n\n\n\n<p>On the VM, install SQL Server Developer Edition (or another supported edition). Microsoft\u2019s installation steps can change by distro\/version, so follow the official SQL Server on Linux install guide and then return here.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Official docs entry point (verify current version steps):<br\/>\n  https:\/\/learn.microsoft.com\/sql\/linux\/sql-server-linux-setup<\/li>\n<\/ul>\n\n\n\n<p>After installation:\n1. Ensure SQL Server is running\n2. Enable TCP\/IP on port 1433 (default on Linux installs)\n3. Set the <code>sa<\/code> password and confirm local connectivity<\/p>\n\n\n\n<p><strong>Install sqlcmd tooling (for validation on Linux):<\/strong><br\/>\nFollow the official <code>sqlcmd<\/code> installation guide (package names vary by distro\/version):\n&#8211; https:\/\/learn.microsoft.com\/sql\/tools\/sqlcmd\/sqlcmd-utility<\/p>\n\n\n\n<p><strong>Create a sample database and table<\/strong>\nRun on the VM (adjust <code>SA_PASSWORD<\/code> as set during install):<\/p>\n\n\n\n<pre><code class=\"language-bash\">export SA_PASSWORD='YourStrong!Passw0rd'\n\/opt\/mssql-tools*\/bin\/sqlcmd -S localhost -U sa -P \"$SA_PASSWORD\" -Q \"SELECT @@VERSION;\"\n<\/code><\/pre>\n\n\n\n<p>Create a database and insert rows:<\/p>\n\n\n\n<pre><code class=\"language-bash\">\/opt\/mssql-tools*\/bin\/sqlcmd -S localhost -U sa -P \"$SA_PASSWORD\" -Q \"\nCREATE DATABASE DmsLabDb;\nGO\n\"\n<\/code><\/pre>\n\n\n\n<p>Now create schema and data:<\/p>\n\n\n\n<pre><code class=\"language-bash\">\/opt\/mssql-tools*\/bin\/sqlcmd -S localhost -U sa -P \"$SA_PASSWORD\" -d DmsLabDb -Q \"\nCREATE TABLE dbo.Customers\n(\n  CustomerId INT IDENTITY(1,1) PRIMARY KEY,\n  FullName NVARCHAR(200) NOT NULL,\n  Email NVARCHAR(320) NULL,\n  CreatedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME()\n);\n\nINSERT INTO dbo.Customers (FullName, Email) VALUES\n('Ada Lovelace','ada@example.com'),\n('Grace Hopper','grace@example.com'),\n('Linus Torvalds','linus@example.com');\n\nSELECT COUNT(*) AS CustomerCount FROM dbo.Customers;\n\"\n<\/code><\/pre>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\n<code>CustomerCount<\/code> returns <code>3<\/code>.<\/p>\n\n\n\n<p><strong>Verification:<\/strong><br\/>\nAlso capture the VM private IP (needed for DMS to connect):<\/p>\n\n\n\n<pre><code class=\"language-bash\">hostname -I\n<\/code><\/pre>\n\n\n\n<p>Record the VM private IP address (example: <code>10.10.1.4<\/code>).<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Create the Azure SQL Database target<\/h3>\n\n\n\n<p><strong>Why:<\/strong> DMS needs a target database provisioned in Azure.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Azure Portal \u2192 Create \u2192 <strong>Azure SQL<\/strong> \u2192 <strong>SQL Database<\/strong><\/li>\n<li>Create a new SQL server (logical server) with:\n   &#8211; SQL authentication admin user and password (store securely)\n   &#8211; Region same as DMS for best performance<\/li>\n<li>Choose a low-cost tier for testing (any tier that meets minimum needs). Exact tier naming changes; select something entry-level for labs.<\/li>\n<\/ol>\n\n\n\n<p><strong>Networking:<\/strong>\n&#8211; For simplest lab connectivity, use the default public endpoint and set:\n  &#8211; Add your client IP to firewall rules (so you can validate with a client)\n  &#8211; Enable the Azure SQL server setting often called <strong>\u201cAllow Azure services and resources to access this server\u201d<\/strong> (wording may vary). This can help DMS reach the server.<\/p>\n\n\n\n<blockquote>\n<p>Security note: In production, prefer <strong>private endpoints<\/strong> and strict firewall rules. For a lab, the \u201cAllow Azure services\u2026\u201d setting is convenient but broader.<\/p>\n<\/blockquote>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nAn Azure SQL Database exists and is reachable.<\/p>\n\n\n\n<p><strong>Verification (optional from VM):<\/strong>\nInstall <code>sqlcmd<\/code> (already installed for SQL Server) and test connecting to Azure SQL:<\/p>\n\n\n\n<pre><code class=\"language-bash\">\/opt\/mssql-tools*\/bin\/sqlcmd -S tcp:&lt;your-sql-server-name&gt;.database.windows.net,1433 \\\n  -U &lt;sql-admin-user&gt; -P '&lt;sql-admin-password&gt;' -d &lt;db-name&gt; \\\n  -Q \"SELECT @@VERSION;\"\n<\/code><\/pre>\n\n\n\n<p>If your Azure SQL firewall blocks the VM, run validation from your workstation instead, after allowing your IP.<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Create Azure Database Migration Service<\/h3>\n\n\n\n<p><strong>Why:<\/strong> This is the migration runtime that will connect to source SQL Server and target Azure SQL Database.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Azure Portal \u2192 Create a resource \u2192 search for <strong>Azure Database Migration Service<\/strong><\/li>\n<li>Create the service:\n   &#8211; Subscription + resource group: <code>rg-dms-lab<\/code>\n   &#8211; Name: <code>dms-lab-001<\/code>\n   &#8211; Region: same as VNet and Azure SQL\n   &#8211; Select a tier\/SKU that supports <strong>offline SQL Server to Azure SQL Database<\/strong> migrations<br\/>\n     (often a \u201cStandard\u201d tier supports offline migrations; verify current tiers in docs\/pricing)\n   &#8211; Networking: select <code>vnet-dms-lab<\/code> and <code>subnet-dms<\/code><\/li>\n<\/ol>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nDMS resource is deployed successfully into <code>subnet-dms<\/code>.<\/p>\n\n\n\n<p><strong>Verification:<\/strong>\n&#8211; Azure Portal \u2192 DMS resource \u2192 Overview shows \u201cSucceeded\u201d.<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Create a migration project and start an offline migration<\/h3>\n\n\n\n<p>The portal experience can vary by update, but the core inputs are consistent: <strong>source type<\/strong>, <strong>target type<\/strong>, <strong>migration mode<\/strong>, <strong>connectivity details<\/strong>, <strong>database selection<\/strong>, then <strong>run<\/strong>.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the DMS resource in the Azure Portal.<\/li>\n<li>Create a <strong>New Migration Project<\/strong> (name example: <code>sqlserver-to-azuresql-offline-lab<\/code>).<\/li>\n<li>\n<p>Choose:\n   &#8211; <strong>Source server type:<\/strong> SQL Server\n   &#8211; <strong>Target server type:<\/strong> Azure SQL Database\n   &#8211; <strong>Migration activity type:<\/strong> Offline (or \u201coffline data migration\u201d)<\/p>\n<\/li>\n<li>\n<p>Configure <strong>Source<\/strong> connection:\n   &#8211; Server name: VM private IP (example <code>10.10.1.4<\/code>)\n   &#8211; Port: <code>1433<\/code>\n   &#8211; Authentication: SQL Authentication\n   &#8211; User: <code>sa<\/code>\n   &#8211; Password: your <code>sa<\/code> password<br\/>\n   &#8211; Encrypt connection: depends on your setup; if you enabled encryption or require TLS, configure accordingly. If unsure, <strong>verify in docs<\/strong> and prefer encrypted connections in real environments.<\/p>\n<\/li>\n<li>\n<p>Configure <strong>Target<\/strong> connection:\n   &#8211; Azure SQL logical server name (FQDN): <code>&lt;your-sql-server-name&gt;.database.windows.net<\/code>\n   &#8211; Authentication: SQL Authentication (admin or a migration user)\n   &#8211; Ensure target firewall permits DMS (see Step 4 notes)<\/p>\n<\/li>\n<li>\n<p>Select the database:\n   &#8211; <code>DmsLabDb<\/code>\n   &#8211; Select tables (for this lab, <code>dbo.Customers<\/code>)<\/p>\n<\/li>\n<li>Start the migration activity.<\/li>\n<\/ol>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nMigration activity starts and shows progress; eventually it completes successfully.<\/p>\n\n\n\n<p><strong>Verification:<\/strong>\n&#8211; In the migration activity view, confirm:\n  &#8211; Status: Running \u2192 Completed\n  &#8211; Rows migrated for <code>dbo.Customers<\/code> equals <code>3<\/code> (or shows completion without errors)<\/p>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 7: Validate data on the target<\/h3>\n\n\n\n<p>Connect to Azure SQL Database and confirm row counts.<\/p>\n\n\n\n<p>From your workstation (Azure Data Studio\/SSMS) or via <code>sqlcmd<\/code>:<\/p>\n\n\n\n<pre><code class=\"language-bash\">\/opt\/mssql-tools*\/bin\/sqlcmd -S tcp:&lt;your-sql-server-name&gt;.database.windows.net,1433 \\\n  -U &lt;sql-admin-user&gt; -P '&lt;sql-admin-password&gt;' -d &lt;db-name&gt; \\\n  -Q \"SELECT COUNT(*) AS CustomerCount FROM dbo.Customers;\"\n<\/code><\/pre>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\n<code>CustomerCount<\/code> returns <code>3<\/code>.<\/p>\n\n\n\n<p><strong>Additional validation queries (recommended):<\/strong><\/p>\n\n\n\n<pre><code class=\"language-sql\">SELECT TOP 10 * FROM dbo.Customers ORDER BY CustomerId;\nSELECT MIN(CreatedAt) AS MinCreatedAt, MAX(CreatedAt) AS MaxCreatedAt FROM dbo.Customers;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Validation<\/h3>\n\n\n\n<p>Use this checklist to confirm the lab succeeded:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] DMS service deployed in the correct region and subnet<\/li>\n<li>[ ] DMS can reach the source SQL Server VM private IP on port 1433 (NSG allows it)<\/li>\n<li>[ ] DMS can connect to Azure SQL Database (firewall\/\u201cAllow Azure services\u2026\u201d configured)<\/li>\n<li>[ ] Migration activity completes successfully<\/li>\n<li>[ ] Row counts match between source and target<\/li>\n<\/ul>\n\n\n\n<p>To verify source count:<\/p>\n\n\n\n<pre><code class=\"language-bash\">\/opt\/mssql-tools*\/bin\/sqlcmd -S localhost -U sa -P \"$SA_PASSWORD\" -d DmsLabDb -Q \\\n\"SELECT COUNT(*) AS CustomerCount FROM dbo.Customers;\"\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Troubleshooting<\/h3>\n\n\n\n<p>Common issues and realistic fixes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\n<p><strong>DMS deployment fails due to subnet constraints<\/strong>\n   &#8211; Cause: Subnet too small, not dedicated, or has conflicting policies.\n   &#8211; Fix: Create a dedicated subnet (often <code>\/27<\/code> or larger) for DMS and retry. Verify requirements in official docs.<\/p>\n<\/li>\n<li>\n<p><strong>DMS can\u2019t connect to source SQL Server<\/strong>\n   &#8211; Cause: NSG blocks 1433, SQL Server not listening on network interface, wrong private IP.\n   &#8211; Fix:<\/p>\n<ul>\n<li>Confirm VM private IP<\/li>\n<li>Confirm inbound NSG rule allowing <code>10.10.2.0\/27<\/code> \u2192 <code>1433<\/code><\/li>\n<li>Confirm SQL Server listens on <code>0.0.0.0:1433<\/code> (or the VM IP)<\/li>\n<li>Confirm VM firewall (ufw\/iptables) allows 1433 from DMS subnet<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Login failed for user<\/strong>\n   &#8211; Cause: Wrong credentials; SQL auth disabled; password policy.\n   &#8211; Fix: Reset the <code>sa<\/code> password; ensure SQL auth works; test locally with <code>sqlcmd<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>DMS can\u2019t connect to Azure SQL Database<\/strong>\n   &#8211; Cause: Azure SQL firewall blocks DMS; \u201cAllow Azure services\u2026\u201d not enabled; wrong server FQDN.\n   &#8211; Fix:<\/p>\n<ul>\n<li>Confirm server name is <code>&lt;server&gt;.database.windows.net<\/code><\/li>\n<li>Enable \u201cAllow Azure services and resources\u2026\u201d<\/li>\n<li>Ensure target database exists and credentials are correct<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Schema missing on target<\/strong>\n   &#8211; Cause: Some migration flows migrate data only or require schema pre-creation depending on scenario.\n   &#8211; Fix: Create schema first (manually or via supported tooling) and rerun. Verify whether your migration activity migrates schema for your chosen mode.<\/p>\n<\/li>\n<li>\n<p><strong>Performance is slow<\/strong>\n   &#8211; Cause: Small target tier, limited VM size, network bottleneck.\n   &#8211; Fix: Temporarily scale up target tier during migration; verify throughput; run during low usage.<\/p>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n\n<h3 class=\"wp-block-heading\">Cleanup<\/h3>\n\n\n\n<p>To avoid ongoing charges, delete lab resources:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Stop\/delete the VM (and its disks\/public IP).<\/li>\n<li>Delete Azure SQL Database and logical server (after confirming no needed data).<\/li>\n<li>Delete the DMS resource.<\/li>\n<li>Delete the VNet (if not used by anything else).<\/li>\n<li>Delete the resource group <code>rg-dms-lab<\/code> (fastest for full cleanup).<\/li>\n<\/ol>\n\n\n\n<p><strong>Expected outcome:<\/strong><br\/>\nNo chargeable resources remain.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">11. Best Practices<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Architecture best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Decide migration mode early<\/strong> (offline vs online) based on downtime tolerance.<\/li>\n<li>Separate work into phases:\n  1. Assess (compatibility\/performance)\n  2. Pilot (small representative workload)\n  3. Rehearsal (full procedure)\n  4. Production cutover (change-controlled)<\/li>\n<li>Use a <strong>landing zone<\/strong> approach: standardized networking, identity, policies, and logging before migrations.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">IAM\/security best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <strong>least privilege<\/strong>:<\/li>\n<li>Azure RBAC: give operators only what they need (often Contributor on a dedicated RG).<\/li>\n<li>Database permissions: use migration-specific users, not sysadmin, where possible.<\/li>\n<li>Keep secrets out of chat\/tickets; store in a secret manager (for example, <strong>Azure Key Vault<\/strong>) and handle carefully during operator workflows.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Cost best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Delete DMS resources after migration waves if not needed.<\/li>\n<li>Scale Azure SQL target tier up for migration throughput, then scale down after validation.<\/li>\n<li>Minimize rehearsal data volume when practicing, but run at least one full rehearsal before production.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Performance best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Co-locate resources in the same region to reduce latency.<\/li>\n<li>Ensure target is sized to handle migration write load (IOPS\/CPU).<\/li>\n<li>Avoid migrating during peak usage (even for offline, do prep steps off-hours).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Reliability best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Always have a <strong>rollback plan<\/strong>:<\/li>\n<li>For offline: keep original source untouched until validation passes.<\/li>\n<li>For online: have a cutback plan and understand resync implications.<\/li>\n<li>Use maintenance windows with clear go\/no-go criteria.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Operations best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Run migrations with a checklist:<\/li>\n<li>Connectivity validation<\/li>\n<li>Backup verification<\/li>\n<li>Migration start\/end timestamps<\/li>\n<li>Post-migration validation queries<\/li>\n<li>Monitor:<\/li>\n<li>Source: CPU\/memory\/disk, transaction log growth<\/li>\n<li>Target: CPU\/storage\/DTU or vCore metrics, blocking, tempdb usage<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Governance\/tagging\/naming best practices<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tag resources:<\/li>\n<li><code>CostCenter<\/code>, <code>Environment<\/code>, <code>App<\/code>, <code>Owner<\/code>, <code>MigrationWave<\/code><\/li>\n<li>Use consistent names:<\/li>\n<li><code>dms-&lt;app&gt;-&lt;env&gt;-&lt;region&gt;-&lt;nnn&gt;<\/code><\/li>\n<li>Use Azure Policy to enforce:<\/li>\n<li>Allowed regions<\/li>\n<li>Required tags<\/li>\n<li>Private networking requirements (where applicable)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">12. Security Considerations<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Identity and access model<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Azure RBAC<\/strong> governs who can manage Azure Database Migration Service resources and projects.<\/li>\n<li><strong>Database credentials<\/strong> provided to DMS must have the required permissions on source\/target.<\/li>\n<li>Prefer dedicated migration accounts with scoped permissions and rotation after cutover.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Encryption<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use encrypted connections (TLS) where supported for source\/target connections.<\/li>\n<li>Azure SQL encrypts data at rest by default (platform-managed); verify encryption settings for other targets.<\/li>\n<li>For source systems, confirm disk encryption and backup encryption practices.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Network exposure<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Prefer private connectivity:<\/li>\n<li>DMS in a private subnet<\/li>\n<li>Source reachable via private IP (VPN\/ExpressRoute)<\/li>\n<li>Target via private endpoint where feasible<\/li>\n<li>Avoid exposing database ports publicly for the sake of migration.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Secrets handling<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Treat source\/target passwords as high sensitivity:<\/li>\n<li>Store in Key Vault<\/li>\n<li>Use short-lived access where possible<\/li>\n<li>Limit who can view\/edit migration project settings<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Audit\/logging<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use Azure Activity Log to track changes to the DMS resource (creation, deletion, configuration changes).<\/li>\n<li>Database auditing:<\/li>\n<li>Azure SQL auditing can record logins and queries (configure per policy)<\/li>\n<li>Source database audit logs should be preserved during migration windows<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Compliance considerations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ensure data residency requirements match the Azure region.<\/li>\n<li>Validate that your migration path meets regulatory requirements (PII\/PHI handling, encryption-in-transit, access controls).<\/li>\n<li>Document evidence for change control (who ran the migration, when, results, validation).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Common security mistakes<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Allowing public access to source DB \u201cjust for migration\u201d<\/li>\n<li>Leaving broad firewall rules enabled after cutover<\/li>\n<li>Reusing production admin credentials in migration projects<\/li>\n<li>Not rotating secrets after migration<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Secure deployment recommendations<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use private networking and strict NSG rules.<\/li>\n<li>Use separate resource groups and RBAC roles for migration operations.<\/li>\n<li>Perform a pre-migration security review of connectivity and credential handling.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">13. Limitations and Gotchas<\/h2>\n\n\n\n<p>Because capabilities vary by scenario and evolve over time, treat these as common pitfalls and validate details in official docs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Known limitations (scenario-dependent)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Not all source\/target pairs support <strong>online<\/strong> migrations.<\/li>\n<li>Some migrations require <strong>schema to be prepared<\/strong> ahead of time.<\/li>\n<li>Certain database features may not be supported on the target platform (for example, SQL Server instance-level features when moving to Azure SQL Database).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Quotas<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Subnet sizing and dedicated subnet requirements can block deployment.<\/li>\n<li>Throughput is limited by network and target service tier.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Regional constraints<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DMS is regional; not all regions support all features.<\/li>\n<li>Cross-region migrations add latency and complexity\u2014avoid if possible.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Pricing surprises<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Leaving DMS resources running longer than needed can increase cost.<\/li>\n<li>Target database scaling during migration can increase costs (plan scale-down steps).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Compatibility issues<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Collation differences, unsupported data types, or feature gaps can break application behavior.<\/li>\n<li>Azure SQL Database vs SQL Server differences are significant; use assessments and testing.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Operational gotchas<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NSGs and firewalls are the #1 cause of failed connectivity.<\/li>\n<li>DNS resolution issues in VNets (especially with private endpoints) can prevent connections.<\/li>\n<li>Transaction log growth (for online\/replication-based migrations) can cause source disk issues.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Migration challenges<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Large objects (LOBs), very large tables, and high-write workloads need careful planning.<\/li>\n<li>\u201cIt migrated\u201d does not equal \u201cthe app works.\u201d Plan application regression testing.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">14. Comparison with Alternatives<\/h2>\n\n\n\n<p>Azure Database Migration Service is one option in a broader migration toolkit.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Comparison table<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Option<\/th>\n<th>Best For<\/th>\n<th>Strengths<\/th>\n<th>Weaknesses<\/th>\n<th>When to Choose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>Azure Database Migration Service<\/strong><\/td>\n<td>Azure-native database migrations with guided workflows<\/td>\n<td>VNet-integrated runtime, structured projects, offline\/online options depending on scenario<\/td>\n<td>Support and features vary by engine; networking can be complex<\/td>\n<td>When you want an Azure-supported migration execution service<\/td>\n<\/tr>\n<tr>\n<td><strong>Azure SQL migration tooling\/experiences (Microsoft)<\/strong><\/td>\n<td>SQL Server to Azure SQL family migrations<\/td>\n<td>Often provides assessments + guided steps; may integrate multiple components<\/td>\n<td>Tooling changes over time; may be SQL-specific<\/td>\n<td>When migrating to Azure SQL and Microsoft recommends it for your scenario (verify)<\/td>\n<\/tr>\n<tr>\n<td><strong>Native engine tools (backup\/restore, dump\/restore, replication)<\/strong><\/td>\n<td>Simple or highly controlled migrations<\/td>\n<td>Transparent, scriptable, no extra service dependency<\/td>\n<td>More manual orchestration; less centralized tracking<\/td>\n<td>When you want maximum control and have DBA automation expertise<\/td>\n<\/tr>\n<tr>\n<td><strong>Azure Data Factory \/ Synapse pipelines<\/strong><\/td>\n<td>Data movement\/ETL rather than lift-and-shift DB migration<\/td>\n<td>Great for transformation and ongoing integration<\/td>\n<td>Not a full-fidelity DB migration tool<\/td>\n<td>When you are transforming data, not migrating databases as databases<\/td>\n<\/tr>\n<tr>\n<td><strong>Third-party migration tools<\/strong><\/td>\n<td>Complex heterogeneous migrations<\/td>\n<td>Mature wizards, transformations, validations<\/td>\n<td>Licensing cost, vendor lock-in<\/td>\n<td>When you need cross-engine transformations and enterprise migration suites<\/td>\n<\/tr>\n<tr>\n<td><strong>AWS Database Migration Service (AWS)<\/strong><\/td>\n<td>Migrations into AWS<\/td>\n<td>Managed migrations and replication in AWS<\/td>\n<td>Not Azure-native; cross-cloud adds complexity<\/td>\n<td>When your target is AWS, not Azure<\/td>\n<\/tr>\n<tr>\n<td><strong>Google Database Migration Service (GCP)<\/strong><\/td>\n<td>Migrations into GCP<\/td>\n<td>GCP-native migration tooling<\/td>\n<td>Not Azure-native<\/td>\n<td>When your target is GCP<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">15. Real-World Example<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Enterprise example: Hybrid SQL Server estate moving to Azure SQL Managed Instance<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> A company has 50+ SQL Server databases on-prem, strict security policies, and limited downtime windows. Some databases rely on SQL Server instance-level features.<\/li>\n<li><strong>Proposed architecture:<\/strong><\/li>\n<li>ExpressRoute from on-prem to Azure hub VNet<\/li>\n<li>Spoke VNet for migration with Azure Database Migration Service in a dedicated subnet<\/li>\n<li>Target: Azure SQL Managed Instance in a dedicated subnet (plus private DNS)<\/li>\n<li>Controlled cutover waves, with rehearsals in pre-prod<\/li>\n<li><strong>Why Azure Database Migration Service was chosen:<\/strong><\/li>\n<li>Fits private networking requirements<\/li>\n<li>Provides structured project-based migration execution<\/li>\n<li>Supports reduced downtime patterns for some SQL scenarios (verify exact support)<\/li>\n<li><strong>Expected outcomes:<\/strong><\/li>\n<li>Reduced patching\/backup overhead by adopting managed services<\/li>\n<li>Repeatable migration process across waves<\/li>\n<li>Documented cutovers aligned with change control<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Startup\/small-team example: Move from SQL Server on a VM to Azure SQL Database<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Problem:<\/strong> A startup runs SQL Server on a single VM and wants to reduce maintenance while improving availability.<\/li>\n<li><strong>Proposed architecture:<\/strong><\/li>\n<li>Source: SQL Server on VM<\/li>\n<li>Target: Azure SQL Database (General Purpose tier sized for workload)<\/li>\n<li>Azure Database Migration Service for a weekend offline migration<\/li>\n<li><strong>Why Azure Database Migration Service was chosen:<\/strong><\/li>\n<li>Simple migration workflow without building custom scripts<\/li>\n<li>Clear progress tracking and repeatable process<\/li>\n<li><strong>Expected outcomes:<\/strong><\/li>\n<li>Less operational burden (patching, backups, HA)<\/li>\n<li>Easier scaling and monitoring<\/li>\n<li>Faster recovery options using built-in Azure SQL capabilities<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">16. FAQ<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\n<p><strong>Is Azure Database Migration Service the same as Azure Migrate?<\/strong><br\/>\n   No. Azure Migrate is broader (discovery\/assessment across servers\/apps). Azure Database Migration Service focuses on executing database migrations. They are often used together.<\/p>\n<\/li>\n<li>\n<p><strong>Do I always need a VNet for Azure Database Migration Service?<\/strong><br\/>\n   Many common scenarios deploy DMS into a VNet subnet, especially to reach private sources. Exact requirements depend on the migration type\u2014verify in official docs.<\/p>\n<\/li>\n<li>\n<p><strong>Can Azure Database Migration Service migrate schema and data?<\/strong><br\/>\n   It can for some scenarios, while others require you to prepare schema separately. Always confirm your scenario\u2019s workflow in official docs.<\/p>\n<\/li>\n<li>\n<p><strong>What\u2019s the difference between offline and online migration?<\/strong><br\/>\n   Offline is a batch move requiring downtime at cutover. Online aims to reduce downtime by continuously syncing changes until cutover. Online support is scenario-specific.<\/p>\n<\/li>\n<li>\n<p><strong>How do I minimize downtime with DMS?<\/strong><br\/>\n   Use online migrations where supported, rehearse cutover steps, pre-provision target performance, and keep validation automated.<\/p>\n<\/li>\n<li>\n<p><strong>Can I migrate from on-prem to Azure without exposing my database to the internet?<\/strong><br\/>\n   Yes\u2014use VPN\/ExpressRoute and deploy DMS into a VNet with private routing to the source.<\/p>\n<\/li>\n<li>\n<p><strong>Does DMS support migrations from other clouds?<\/strong><br\/>\n   If network connectivity and your source engine are supported, yes. But data egress costs and network design are your responsibility.<\/p>\n<\/li>\n<li>\n<p><strong>How do I estimate how long a migration will take?<\/strong><br\/>\n   Base it on data size, network throughput\/latency, target write capacity, and migration mode. Run a pilot on representative data.<\/p>\n<\/li>\n<li>\n<p><strong>What\u2019s the most common reason migrations fail?<\/strong><br\/>\n   Networking and connectivity: NSGs\/firewalls, DNS, routing, and authentication issues.<\/p>\n<\/li>\n<li>\n<p><strong>Do I need DBA access on the source database?<\/strong><br\/>\n   You need enough permissions to read schema\/data and possibly logs\/replication settings for online migrations. Exact permissions vary by engine and mode.<\/p>\n<\/li>\n<li>\n<p><strong>Can I pause and resume a migration?<\/strong><br\/>\n   Capabilities depend on the migration type and tooling flow. Plan for restartability by keeping source stable and documenting steps. Verify pause\/resume behavior for your scenario.<\/p>\n<\/li>\n<li>\n<p><strong>Should I run DMS in production permanently?<\/strong><br\/>\n   Typically no. It\u2019s used during migration waves and then removed to reduce cost and attack surface.<\/p>\n<\/li>\n<li>\n<p><strong>How do I validate data correctness after migration?<\/strong><br\/>\n   Use row counts, checksums\/hashes (where feasible), sampled data comparisons, application-level tests, and performance tests on target queries.<\/p>\n<\/li>\n<li>\n<p><strong>What about stored procedures, jobs, and users?<\/strong><br\/>\n   It depends on the target platform. For Azure SQL Database, some instance-level features don\u2019t exist. Plan a full \u201cdatabase + surrounding objects\u201d migration strategy.<\/p>\n<\/li>\n<li>\n<p><strong>Where do I find the exact list of supported migrations and prerequisites?<\/strong><br\/>\n   In Microsoft Learn documentation for Azure Database Migration Service and the specific migration tutorial for your source\/target pair:\n   https:\/\/learn.microsoft.com\/azure\/dms\/<\/p>\n<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">17. Top Online Resources to Learn Azure Database Migration Service<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Resource Type<\/th>\n<th>Name<\/th>\n<th>Why It Is Useful<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Official documentation<\/td>\n<td>https:\/\/learn.microsoft.com\/azure\/dms\/<\/td>\n<td>Primary reference for concepts, supported scenarios, and step-by-step guides<\/td>\n<\/tr>\n<tr>\n<td>Official pricing page<\/td>\n<td>https:\/\/azure.microsoft.com\/pricing\/details\/database-migration\/<\/td>\n<td>Authoritative pricing model and tier information<\/td>\n<\/tr>\n<tr>\n<td>Pricing calculator<\/td>\n<td>https:\/\/azure.microsoft.com\/pricing\/calculator\/<\/td>\n<td>Build scenario-based cost estimates (DMS + target DB + network)<\/td>\n<\/tr>\n<tr>\n<td>Azure SQL documentation<\/td>\n<td>https:\/\/learn.microsoft.com\/azure\/azure-sql\/<\/td>\n<td>Target platform details, firewall\/private endpoint guidance, performance tiers<\/td>\n<\/tr>\n<tr>\n<td>SQL Server on Linux docs<\/td>\n<td>https:\/\/learn.microsoft.com\/sql\/linux\/sql-server-linux-setup<\/td>\n<td>Repeatable lab setup for a source SQL Server on Ubuntu<\/td>\n<\/tr>\n<tr>\n<td>sqlcmd utility docs<\/td>\n<td>https:\/\/learn.microsoft.com\/sql\/tools\/sqlcmd\/sqlcmd-utility<\/td>\n<td>Command-line validation and scripting for SQL Server\/Azure SQL<\/td>\n<\/tr>\n<tr>\n<td>Azure networking fundamentals<\/td>\n<td>https:\/\/learn.microsoft.com\/azure\/virtual-network\/<\/td>\n<td>VNets, subnets, NSGs, routing\u2014critical for DMS connectivity<\/td>\n<\/tr>\n<tr>\n<td>Azure VPN Gateway<\/td>\n<td>https:\/\/learn.microsoft.com\/azure\/vpn-gateway\/<\/td>\n<td>Hybrid connectivity patterns often used for production migrations<\/td>\n<\/tr>\n<tr>\n<td>ExpressRoute<\/td>\n<td>https:\/\/learn.microsoft.com\/azure\/expressroute\/<\/td>\n<td>Private connectivity for enterprise-scale hybrid migrations<\/td>\n<\/tr>\n<tr>\n<td>Azure Architecture Center<\/td>\n<td>https:\/\/learn.microsoft.com\/azure\/architecture\/<\/td>\n<td>Reference architectures and best practices that inform migration designs<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">18. Training and Certification Providers<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Institute<\/th>\n<th>Suitable Audience<\/th>\n<th>Likely Learning Focus<\/th>\n<th>Mode<\/th>\n<th>Website URL<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>DevOpsSchool.com<\/td>\n<td>DevOps engineers, SREs, cloud engineers<\/td>\n<td>Azure operations, DevOps practices, migration-adjacent skills<\/td>\n<td>Check website<\/td>\n<td>https:\/\/www.devopsschool.com\/<\/td>\n<\/tr>\n<tr>\n<td>ScmGalaxy.com<\/td>\n<td>Beginners to intermediate practitioners<\/td>\n<td>DevOps\/SCM fundamentals, automation foundations<\/td>\n<td>Check website<\/td>\n<td>https:\/\/www.scmgalaxy.com\/<\/td>\n<\/tr>\n<tr>\n<td>CLoudOpsNow.in<\/td>\n<td>Cloud engineers and operators<\/td>\n<td>Cloud ops, deployment\/operations skills<\/td>\n<td>Check website<\/td>\n<td>https:\/\/www.cloudopsnow.in\/<\/td>\n<\/tr>\n<tr>\n<td>SreSchool.com<\/td>\n<td>SREs, platform teams<\/td>\n<td>Reliability engineering, monitoring, incident response<\/td>\n<td>Check website<\/td>\n<td>https:\/\/www.sreschool.com\/<\/td>\n<\/tr>\n<tr>\n<td>AiOpsSchool.com<\/td>\n<td>Ops teams exploring AIOps<\/td>\n<td>Monitoring automation, AIOps concepts<\/td>\n<td>Check website<\/td>\n<td>https:\/\/www.aiopsschool.com\/<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">19. Top Trainers<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Platform\/Site<\/th>\n<th>Likely Specialization<\/th>\n<th>Suitable Audience<\/th>\n<th>Website URL<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>RajeshKumar.xyz<\/td>\n<td>DevOps\/cloud training content (verify offerings)<\/td>\n<td>Students, working professionals<\/td>\n<td>https:\/\/rajeshkumar.xyz\/<\/td>\n<\/tr>\n<tr>\n<td>devopstrainer.in<\/td>\n<td>DevOps training (verify course coverage)<\/td>\n<td>Beginners to intermediate DevOps engineers<\/td>\n<td>https:\/\/www.devopstrainer.in\/<\/td>\n<\/tr>\n<tr>\n<td>devopsfreelancer.com<\/td>\n<td>Freelance DevOps help\/training platform (verify)<\/td>\n<td>Teams seeking short-term help<\/td>\n<td>https:\/\/www.devopsfreelancer.com\/<\/td>\n<\/tr>\n<tr>\n<td>devopssupport.in<\/td>\n<td>DevOps support\/training (verify)<\/td>\n<td>Ops\/DevOps teams needing guidance<\/td>\n<td>https:\/\/www.devopssupport.in\/<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">20. Top Consulting Companies<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Company Name<\/th>\n<th>Likely Service Area<\/th>\n<th>Where They May Help<\/th>\n<th>Consulting Use Case Examples<\/th>\n<th>Website URL<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>cotocus.com<\/td>\n<td>Cloud\/DevOps consulting (verify exact offerings)<\/td>\n<td>Migration planning, cloud ops, implementation support<\/td>\n<td>Migration runbooks, Azure landing zone alignment, cutover planning<\/td>\n<td>https:\/\/cotocus.com\/<\/td>\n<\/tr>\n<tr>\n<td>DevOpsSchool.com<\/td>\n<td>Training + consulting services (verify catalog)<\/td>\n<td>DevOps transformation, cloud migration assistance<\/td>\n<td>Building CI\/CD for migration tooling, operational readiness<\/td>\n<td>https:\/\/www.devopsschool.com\/<\/td>\n<\/tr>\n<tr>\n<td>DEVOPSCONSULTING.IN<\/td>\n<td>DevOps consulting (verify exact offerings)<\/td>\n<td>DevOps practices, automation, cloud enablement<\/td>\n<td>IaC standardization, environment automation for migration waves<\/td>\n<td>https:\/\/www.devopsconsulting.in\/<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">21. Career and Learning Roadmap<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">What to learn before Azure Database Migration Service<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Database fundamentals:<\/li>\n<li>Backups\/restores, transaction logs, indexing, constraints<\/li>\n<li>Basic performance troubleshooting<\/li>\n<li>Azure fundamentals:<\/li>\n<li>Resource groups, RBAC, VNets\/subnets, NSGs<\/li>\n<li>Target platform basics:<\/li>\n<li>Azure SQL Database vs Azure SQL Managed Instance differences<\/li>\n<li>Authentication and firewall\/private endpoint patterns<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">What to learn after<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Advanced migration patterns:<\/li>\n<li>Online migration prerequisites and change data capture concepts<\/li>\n<li>Data validation automation and reconciliation<\/li>\n<li>Production operations:<\/li>\n<li>Azure Monitor, alerting, auditing<\/li>\n<li>Cost management and capacity planning<\/li>\n<li>Modernization:<\/li>\n<li>Refactoring apps for managed databases<\/li>\n<li>Resiliency patterns and DR design in Azure<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Job roles that use it<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Cloud engineer \/ cloud migration engineer<\/li>\n<li>DBA \/ database platform engineer<\/li>\n<li>Solutions architect<\/li>\n<li>DevOps \/ SRE (cutover and reliability support)<\/li>\n<li>Security engineer (networking and access reviews)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Certification path (Azure)<\/h3>\n\n\n\n<p>Microsoft certification names and requirements change. Consider:\n&#8211; Azure fundamentals and administrator tracks\n&#8211; Azure database-focused learning paths\n&#8211; Architecture certifications for end-to-end migration design<br\/>\n<strong>Verify current certification options on Microsoft Learn<\/strong>: https:\/\/learn.microsoft.com\/credentials\/<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Project ideas for practice<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Migrate SQL Server on a VM to Azure SQL Database and implement:<\/li>\n<li>Private endpoints<\/li>\n<li>Azure AD authentication (where supported)<\/li>\n<li>Automated validation scripts<\/li>\n<li>Build a \u201cmigration factory\u201d:<\/li>\n<li>Standard naming\/tagging<\/li>\n<li>Pre-flight network checks<\/li>\n<li>Automated target provisioning and post-migration smoke tests<\/li>\n<li>Compare offline vs online approaches with measurable downtime and performance metrics (where supported)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">22. Glossary<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cutover<\/strong>: The moment you switch the application from the source database to the target database.<\/li>\n<li><strong>Offline migration<\/strong>: A migration mode where data is moved in batch; typically requires downtime at cutover.<\/li>\n<li><strong>Online migration<\/strong>: A migration mode designed to reduce downtime by continuously syncing changes until cutover (scenario-dependent).<\/li>\n<li><strong>Source<\/strong>: The database system you are migrating from.<\/li>\n<li><strong>Target<\/strong>: The Azure database service you are migrating to.<\/li>\n<li><strong>VNet (Virtual Network)<\/strong>: Azure networking boundary used to isolate and route traffic privately.<\/li>\n<li><strong>Subnet<\/strong>: A range of IP addresses within a VNet; DMS often requires a dedicated subnet.<\/li>\n<li><strong>NSG (Network Security Group)<\/strong>: Azure firewall-like rules controlling inbound\/outbound traffic to subnets\/NICs.<\/li>\n<li><strong>Private endpoint<\/strong>: A private IP interface in your VNet that connects to an Azure PaaS service privately.<\/li>\n<li><strong>Azure RBAC<\/strong>: Role-Based Access Control for managing access to Azure resources.<\/li>\n<li><strong>Logical SQL Server (Azure SQL)<\/strong>: The Azure resource that hosts Azure SQL Databases and defines firewall\/auth settings.<\/li>\n<li><strong>Throughput<\/strong>: Effective data transfer rate during migration, constrained by network and system performance.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">23. Summary<\/h2>\n\n\n\n<p>Azure Database Migration Service is Azure\u2019s managed service for <strong>orchestrating and executing database migrations<\/strong> into Azure targets. It matters because migrations require more than data copy\u2014they require secure connectivity, repeatable workflows, and operational visibility, especially in enterprise environments.<\/p>\n\n\n\n<p>It fits best as the <strong>migration execution engine<\/strong> in an Azure migration program, often working alongside assessment tools and landing zone architectures. Cost is primarily driven by <strong>service tier and runtime duration<\/strong>, plus the frequently larger costs of <strong>target database sizing<\/strong> and hybrid networking. Security success depends on <strong>private networking, least privilege access, and disciplined secrets handling<\/strong>.<\/p>\n\n\n\n<p>Use Azure Database Migration Service when you want an Azure-native, structured migration approach and your source\/target scenario is supported. Next, deepen your skills by validating your scenario against Microsoft\u2019s support matrix and running a rehearsal migration using the official documentation: https:\/\/learn.microsoft.com\/azure\/dms\/<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Migration<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40,46],"tags":[],"class_list":["post-483","post","type-post","status-publish","format-standard","hentry","category-azure","category-migration"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/483","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/comments?post=483"}],"version-history":[{"count":0,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/483\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/media?parent=483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/categories?post=483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/tags?post=483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}