{"id":106091,"date":"2025-03-31T03:24:42","date_gmt":"2025-03-31T03:24:42","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=106091"},"modified":"2026-05-21T15:13:32","modified_gmt":"2026-05-21T15:13:32","slug":"managed-instance-gotchas-error-conditions","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/managed-instance-gotchas-error-conditions\/","title":{"rendered":"5 key problems from a SQL Server to Azure SQL Managed Instance migration (and how to avoid them)"},"content":{"rendered":"\n<p><strong>Azure SQL Managed Instance (MI) sits in a useful middle ground. It has most of the functionality of a full on-premises SQL Server, with Microsoft handling the engine, backups, OS, and hardware. Plus, it supports cross-database queries and SQL Agent jobs, with fewer limits than Azure SQL Database &#8211; making it popular for migrating transactional workloads.<\/strong><\/p>\n\n\n\n<p><strong>The migration itself isn&#8217;t seamless, however. This article reveals the five surprises I encountered from a real production SQL Server to Azure SQL MI migration<\/strong> <strong>&#8211; and what I learned from them. Includes guidance and advice to make your migration as seamless as possible.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-a-bit-of-background\">A bit of background<\/h2>\n\n\n\n<p>I was recently on a project to migrate a very transactional installation of SQL Server to Azure SQL Managed Instance (MI). SQL Managed Instance is a good stepping stone between a full, on-premises SQL instance \/ Azure VM and an Azure SQL Database. It has most of the functionality of a full, on-prem instance, with management of the SQL engine, backups, OS and underlying hardware done by Microsoft. It allows you to use cross database queries and run SQL Agent jobs, with fewer limitations than Azure SQL Database migrations.<\/p>\n\n\n\n<p>The migration process isn\u2019t completely seamless. During the migration of this system, we encountered several surprises &#8211; five of which are detailed in this article. Hopefully, this will help you avoid, or at least be prepared for these differences from the on-prem version. This also reinforces the importance of testing each aspect of your migration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-5-key-problems-i-encountered-and-what-i-learned-from-them\">The 5 key problems I encountered &#8211; and what I learned from them<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-there-s-no-support-for-dns-aliases\">There&#8217;s no support for DNS aliases<\/h3>\n\n\n\n<p>If you plan on using DNS aliases to assist the transition to managed instances, know that it isn\u2019t supported. There may be some way to hack a solution, but that\u2019s generally not a good idea. We tried to use aliases to allow clients\/ external systems to make the DNS name transition before our production migration. <\/p>\n\n\n\n<p>To put it simply, this was a failure. The Azure environment blocks these aliases. You can only use the Microsoft assigned DNS entry. There are likely also certificate issues if using your own alias. You may be able to hack some solution, but that would be fragile at best, and unsupported.<\/p>\n\n\n\n<p>Plan on client applications migrating at the same time as your server migration. In a best-case scenario, the number of clients hitting your system directly will be limited. But be ready for this coordination when you migrate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-zone-redundancy\">Zone redundancy<\/h3>\n\n\n\n<p>An attractive aspect of migrating to MI is the high-availability options available. Zone redundancy synchronizes your server between zones in Azure (refer to the references for detailed zone redundancy information). This is the high-availability option. If a datacenter has issues, your server will fail-over to another zone in your region, when using zone redundancy.<\/p>\n\n\n\n<p>We had significant problems with zone redundancy. After our initial deployments, we enabled zone redundancy in our dev environment. This was successful. After testing, we tried to enable zone redundancy in production. Because server and CPU resources weren\u2019t available in this region (during this deployment), all of our deployments failed. Even environments that were established failed to deploy with no changes.<\/p>\n\n\n\n<p>After many discussions internally, talking to our Microsoft liaisons, and opening a Microsoft ticket, we found that the documentation was incomplete. Zone redundancy was not available in our region and likely will not be available until the 4<sup>th<\/sup> quarter of this year. We had this error even though we had successfully enabled zone redundancy in one of our environments.<\/p>\n\n\n\n<p>This is error we saw in our DevOps environment during our attempted deploy:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\u201ccode\u201d:\u201dManagedInstanceZoneRedundantFeatureTemporarilyDisabledPerHardwareGeneration\u201d,\u201dmessage\u201d,\u201dCreation of ZoneRedundant SQL MI is temporarily disabled for this hardware generation on this region. You can create Zone Redundant SQL Managed Instances with different hardware generation on this region or many other regions in Azure...\u201d}<\/pre>\n\n\n\n<p>The lesson learned from this is, confirm that the options you want to use are available before you plan your migration. The documentation is incomplete. Demand for services in Azure is very high and documented resources may be inaccurate. Consult your Azure representative to verify your plan. Even if it works once, you may be unable to deploy later due to these limitations.<\/p>\n\n\n\n<section id=\"my-first-block-block_2b014240f69c4695a5c4e7ff0c9956e8\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Fast, reliable and consistent SQL Server development&#8230;<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            &#8230;with SQL Toolbelt Essentials. 10 ingeniously simple tools for accelerating development, reducing risk, and standardizing workflows.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/products\/sql-toolbelt-essentials\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Learn more &amp; try for free: Fast, reliable and consistent SQL Server development...\">Learn more &amp; try for free<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-tde-enabled-databases\">TDE-enabled databases<\/h2>\n\n\n\n<p>Moving to Azure Managed Instances is a commitment. If you want to have all of the benefits of a managed server, that probably includes having Microsoft manage the keys for your TDE (encryption at rest) enabled databases. The initial transfer of your databases is a little complicated if it\u2019s TDE enabled. You either need to manage your own keys, which complicates things considerably in the long run, or make the switch to Microsoft managed keys.<\/p>\n\n\n\n<p>If you continue to use your own keys, you need to manage them in Azure SQL MI. This negates some benefits of migrating to MI (primarily, key management and unmanaged PITR restore options between environments). Assuming you don\u2019t want to manage keys, the steps to migrate a TDE enabled database are the following:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Disable TDE on the source database<br><br><\/li>\n\n\n\n<li>Backup the source database<br><br><\/li>\n\n\n\n<li>Copy the backup to an MI accessible location (blob storage)<br><br><\/li>\n\n\n\n<li>Restore the backup<br><br><\/li>\n\n\n\n<li>Enable TDE on the MI<br><br><\/li>\n\n\n\n<li>Delete the unencrypted backups<br><br><\/li>\n\n\n\n<li>Re-enable TDE on the source system (if the source database is not immediately deleted)<\/li>\n<\/ul>\n<\/div>\n\n\n<p>Using Microsoft managed keys allows Point-in-Time-Recovery (PITR) to become seamless between environments, including databases protected with TDE, and key management is handled for you. The extra steps are well worth the migration effort. Remember to allow extra time in your migration for the decryption \/ encryption steps. This will vary considerably depending on your database size, MI performance tier, and source hardware.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-traditional-backup-restore\">Traditional backup\/restore<\/h2>\n\n\n\n<p>Backup and restore options when using MI are limited. Point in time restore (PITR) is the recommended method and provides the most functionality. It allows restores between different databases on the same server to be easily synchronized. One of the primary reasons for moving to MI instead of individual SQL Databases is cross database queries and dependencies between databases. PITR makes this easier.<\/p>\n\n\n\n<p>You can still use the traditional backup \/ restore process in MI environments, with limitations. You need to use a COPY_ONLY backup. To limit scope of our migration effort, we continued to use our old backup \/ restore process between environments using a COPY_ONLY backup scenario. This worked most of the time. Most of the time is a problem with things like backups and restores. Some of our restores failed. Since our databases were interdependent, one database failing left the entire environment unreliable and potentially unusable.<\/p>\n\n\n\n<p>Our failure and diagnosis looked like the following:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Copy Only restore attempted<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Failed after an extended period of time with \u201cUnable to cycle error log\u201d message<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Unable to cycle error log file from &lt;FileLocation> to &lt;FileLocation> due to OS error \u201832(The process cannot access the file because it is being used by another process.). A process outside of SQL Server may be preventing SQL Server from reading the files.<\/li>\n<\/ul>\n<\/div><\/li>\n\n\n\n<li>The restore may work on different servers \/ environments<\/li>\n\n\n\n<li>Database restores for the same server may work for different databases<br><br><\/li>\n<\/ul>\n<\/div><\/li>\n\n\n\n<li>Errors start to show up in the server error log soon after the restore starts (well before the error message is returned to the restore process)<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Page corruption<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>RESTORE detected an error on page (1:12345) in database &lt;GUID> as read from the backup set.<\/li>\n\n\n\n<li>[CorruptedPageList: InsertEntryImITS]: Page (1:45678) in database &lt;GUID> is suspect<\/li>\n\n\n\n<li>Error: 3183, Severity: 16, State: 1<br><br><\/li>\n<\/ul>\n<\/div><\/li>\n<\/ul>\n<\/div><\/li>\n\n\n\n<li>DBCC CHECKDB run on source database<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>No issues<\/li>\n\n\n\n<li>This was the nightmare scenario \u2013 needed it to be ruled out as soon as possible<br><br><\/li>\n<\/ul>\n<\/div><\/li>\n\n\n\n<li>RESTORE VERIFYONLY run against backup file<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>No issues<\/li>\n\n\n\n<li>Backup was able to be restored to a different server<\/li>\n<\/ul>\n<\/div><\/li>\n<\/ul>\n<\/div>\n\n\n<p>The restore process didn\u2019t fail on every server. This, in addition to checking the source with CHECKDB and the restore with VERIFYONLY, indicated that it was a problem with the destination server. This item also involved opening a Microsoft ticket after checking with our Microsoft architect. The issue seemed to be I\/O buffer related. Using the following options during the restore fixed the issue:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>Restore options added<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>BLOCKSIZE = 65536<\/li>\n\n\n\n<li>MAXTRANSFERSIZE = 4194304<\/li>\n<\/ul>\n<\/div><\/li>\n<\/ul>\n<\/div>\n\n\n<p>This fixed the issue, but PITR is the recommended method for SQL MI backups and restores. It\u2019s what you should plan on using. Using a traditional, COPY_ONLY, backup method is technical debt. The first question asked by every level of support was, \u201cWhy aren\u2019t you using PITR?\u201d. Move to PITR as soon as possible for all of your MI processes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-sql-agent-job-errors\">SQL agent job errors<\/h3>\n\n\n\n<p>The final blocker for us to migrate to SQL MI was SQL Agent job errors. In our non-production environments, we had errors requiring investigation and changes to the servers by Microsoft. They were intermittent issues, making fixing this very difficult. Resolving the errors required us to open Microsoft support tickets.<\/p>\n\n\n\n<p>The Agent job issue was relatively easy to fix, since our Microsoft architect was able to find it in the internal support database. That database is not available to customers, so it was only accessible by our support team.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Unable to connect to SQL Server \u2018tcp:localhost,11000\u2019. The step failed<\/pre>\n\n\n\n<p>We don\u2019t interact with localhost, so it was clear it wasn\u2019t our issue. We also don\u2019t specify port 11,000. We also saw ports above 11,000 (i.e., localhost,11007) \u2013 which we also don\u2019t specify. (both of these items were verified by querying the job step table, dbo.sysjobsteps, in msdb). The fix for this was out of our hands. The Microsoft team had to roll back an ODBC driver on the server. After the driver was reverted, this error disappeared.<\/p>\n\n\n\n<p>Agent Jobs are one of the reasons for selecting SQL MI, so this was very disruptive. We will eventually move to a different technology, such as Elastic Jobs or ADF, but be sure thoroughly test your jobs under load.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-summary\">Summary<\/h2>\n\n\n\n<p>SQL Managed Instances are attractive to enterprises that don\u2019t want to be responsible for all of the maintenance of a full SQL Server installation. That includes backups and engine maintenance. We encountered a few issues that would have stopped our migration if we hadn\u2019t tested first or had help from the various Microsoft teams.<\/p>\n\n\n\n<p>We were able to hit our deadlines and had a successful migration, but \u2013 it wasn\u2019t a smooth process. There are a few items that may hamper your migration. If you know about these issues before you begin, you are more likely to be successful. Test thoroughly, talk to the technical team about hardware availability in your region, and be ready to open tickets to resolve issues. And check your error logs during and after the migration. I\u2019ll discuss other differences and surprises in SQL MI in later posts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-references\">References<\/h2>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/managed-instance\/high-availability-sla-local-zone-redundancy?view=azuresql\">https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/managed-instance\/high-availability-sla-local-zone-redundancy?view=azuresql<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/managed-instance\/point-in-time-restore?view=azuresql&amp;tabs=azure-portal\">https:\/\/learn.microsoft.com\/en-us\/azure\/azure-sql\/managed-instance\/point-in-time-restore?view=azuresql&amp;tabs=azure-portal<\/a><\/li>\n<\/ul>\n<\/div>\n\n\n<section id=\"my-first-block-block_ae177b5e24162feed19ca145739e9ea9\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Simple Talk is brought to you by Redgate Software<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            Take control of your databases with the trusted Database DevOps solutions provider. Automate with confidence, scale securely, and unlock growth through AI.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/solutions\/overview\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Discover how Redgate can help you: Simple Talk is brought to you by Redgate Software\">Discover how Redgate can help you<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs: Migrating to Azure SQL Managed Instance<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. Are DNS aliases supported in Azure SQL Managed Instance?<\/h3>\n            <div class=\"faq-answer\">\n                <p class=\"font-claude-response-body break-words whitespace-normal leading-[1.7]\">No. Azure blocks DNS aliases for SQL MI, and you can only use the Microsoft-assigned DNS entry. Custom aliases also create certificate issues. Plan to migrate client applications at the same time as the server &#8211; there&#8217;s no clean way to stage the DNS transition ahead of cutover.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. Is zone redundancy always available for Azure SQL MI?<\/h3>\n            <div class=\"faq-answer\">\n                <p>No. Zone redundancy availability depends on region and hardware generation, and the documentation can be incomplete or out of date. It&#8217;s possible to enable zone redundancy successfully in one environment and then have production deployments fail with <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">ManagedInstanceZoneRedundantFeatureTemporarilyDisabledPerHardwareGeneration<\/code>. Confirm availability with your Azure representative before planning around it.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. How do you migrate a TDE-enabled database to Azure SQL Managed Instance?<\/h3>\n            <div class=\"faq-answer\">\n                <p class=\"font-claude-response-body break-words whitespace-normal leading-[1.7]\">If you&#8217;re switching to Microsoft-managed keys (recommended): disable TDE on the source, back it up, copy to blob storage, restore on MI, re-enable TDE on MI, delete the unencrypted backups, and re-enable TDE on the source if it&#8217;s staying online. Managed keys make Point in Time Recovery seamless across environments. Allow extra migration time for the decrypt\/encrypt steps.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">4. Why do traditional COPY_ONLY restores fail on Azure SQL MI?<\/h3>\n            <div class=\"faq-answer\">\n                <p class=\"font-claude-response-body break-words whitespace-normal leading-[1.7]\">Some COPY_ONLY restores fail with &#8220;Unable to cycle error log&#8221; or page corruption errors that aren&#8217;t present on the source (CHECKDB and RESTORE VERIFYONLY both pass). It&#8217;s an I\/O buffer issue on the destination. Adding <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">BLOCKSIZE = 65536<\/code> and <code class=\"bg-text-200\/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]\">MAXTRANSFERSIZE = 4194304<\/code> to the restore resolves it &#8211; but PITR is the recommended approach and what Microsoft support will steer you toward.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">5. Why are SQL Agent jobs failing with &quot;tcp:localhost,11000&quot; errors?<\/h3>\n            <div class=\"faq-answer\">\n                <div class=\"[content-visibility:auto] [contain-intrinsic-size:auto_400px] pb-8 -mb-8 print:[content-visibility:visible]\">\n<div data-test-render-count=\"1\">\n<div class=\"group\">\n<div class=\"contents\">\n<div class=\"group relative relative pb-3\" data-is-streaming=\"false\">\n<div class=\"font-claude-response relative leading-[1.65rem] [&amp;_pre&gt;div]:bg-bg-000\/50 [&amp;_pre&gt;div]:border-0.5 [&amp;_pre&gt;div]:border-border-400 [&amp;_.ignore-pre-bg&gt;div]:bg-transparent [&amp;_.standard-markdown_:is(p,blockquote,h1,h2,h3,h4,h5,h6)]:pl-2 [&amp;_.standard-markdown_:is(p,blockquote,ul,ol,h1,h2,h3,h4,h5,h6)]:pr-8 [&amp;_.progressive-markdown_:is(p,blockquote,h1,h2,h3,h4,h5,h6)]:pl-2 [&amp;_.progressive-markdown_:is(p,blockquote,ul,ol,h1,h2,h3,h4,h5,h6)]:pr-8\">\n<div>\n<div class=\"standard-markdown grid-cols-1 grid [&amp;_&gt;_*]:min-w-0 gap-3 standard-markdown\">\n<p class=\"font-claude-response-body break-words whitespace-normal leading-[1.7]\">This is a Microsoft-side issue tied to an ODBC driver on the managed instance, not something in your job configuration. The fix requires Microsoft to roll back the driver on the server, which means opening a support ticket. Test Agent jobs under load before cutover.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Planning an Azure SQL Managed Instance migration? Here are five surprises a real transactional SQL Server move uncovered &#8211; and how to avoid them.&hellip;<\/p>\n","protected":false},"author":19670,"featured_media":105890,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":true,"footnotes":""},"categories":[137091,10,143523,143524],"tags":[145474,5336,4168,4150,4151],"coauthors":[98702],"class_list":["post-106091","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-cloud","category-databases","category-sql-server","tag-azure-sql-managed-instance","tag-cloud","tag-database","tag-sql","tag-sql-server"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/106091","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/19670"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=106091"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/106091\/revisions"}],"predecessor-version":[{"id":110835,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/106091\/revisions\/110835"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/105890"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=106091"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=106091"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=106091"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=106091"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}