Traditionally, migration of software solutions from one platform to another has been tedious and riskful (do I need to mention all the horror stories of migration of apps between different versions of Windows Server?). And often the only choice is to do a Big Bang migration where the whole newly-migrated system is released and deployed at a single event. Countless are the times where I, as a developer, have been sitting up all night fixing issues caused by a Big Bang migration. You can only test so much – the real test is production (TM).
The steps presented in this blog post are based on hard-earned experience in the assessment and migration of a lot of legacy apps to Microsoft Azure. You will not find these steps in the Azure Documentation or any books (to my knowledge, at least). Feel to give me some feedback in the comments section.
I use the word “web app” in this blog post to describe a software system which ultimately exposes its functionality through web technologies (e.g. as a website/HTML to a web browser, or as a REST/SOAP APIs to an API client). A “web app” can consist of web apps (e.g., ASP.NET MVC app) or API apps, as well as databases, file share, queues etc.
In this step, your whole legacy web app still runs production on-premises in some non-Azure datacenter. Either in your own data center or at your hosting provider’s data center – or somewhere else. Before deploying (to production) a full migration of your legacy app to Azure, it is important to get accurate insights into how the application runs in production. You can add support for Application Insights (actually, it is now called Azure Monitor, but that’s another story) to many legacy web apps with little or no code changes (especially for .NET and Java apps).
Once you add Azure Application Insights support to the legacy on-prem web app, you get a lot of valuable insights. Here are some things to look out for:
Having a single well-defined endpoint for each web app is important: a consumer of the web app (e.g., a web browser, if it is a website, or a REST client, if it is an API app) knows that if a well-defined endpoint is called, you will always reach the desired web app. Behind the scenes, you might still hit the on-prem web app, or you might hit a newly-migrated Azure instance of the same web app. But the consumer of the web app doesn’t care. The consumer only wants to talk to the web app regardless if it resides in Azure or on-prem.
The traffic routing services that I use the most in this step are:
Common to the above three services is that they all support weighted traffic routing which is needed in Step 5.
Note that Azure Application Gateway and Azure API Management also route HTTP traffic, and in Step 6 you get some hints on how to clean things up, so you don’t end up running redundant services.
Also, note that it requires some work and planning to apply this routing infrastructure to production. But it is not rocket science either.
Most legacy apps use some databases (often MS SQL Server, MySQL or Oracle) to store relational data, and some file shares to store PDF’s or JPG’s (or other files).
In this step, we move the databases and file shares to Azure one-by-one.
I often use:
Again, this is not a trivial task and it might not always work in practice. I assume that you have already verified that it works by migrating a non-production environment (e.g., dev, test, QA) to Azure. Also, note that you don’t have to (and probably shouldn’t) move the whole data layer to Azure at once. If your web app consists of independent services with independent data layers, you can introduce them iteratively into production by repeating step 4+5 for each independent service.
A thorough assessment of your whole web app (incl. databases, file shares etc. ) will show the dependencies and priorities of data layer components.
Often your legacy web app (besides the data layer) consists of some websites and some API apps (REST or SOAP).
Instead of deploying all websites and all API at once to production, we can often deploy them one by one. AND we can switch the traffic between the on-prem instance and the Azure instance until we know that the Azure instance can stand on its own feet. That is what I call reducing the blast radius.
So, here is how it is done:
Note that: web apps often also consists of other components, like: batch jobs, windows services, queues, service bus etc. These components are not covered in this blog post but are still important to the migration project.
Now that your legacy app has been successfully migrated to Azure you are done, right? Maybe, maybe not. If you follow the above five steps, you might have added more Azure service than you need because you wanted more control and insights into the different migration steps. But once the migration is done, and the old on-prem infrastructure is ready to sunset, you should take a step back and see if your Azure setup needs a clean-up.
Here are some examples: