Organisations with significant .NET investment often have a mix of old .NET Framework applications, such as 3.5 and 4.x, and newer .NET Core or .NET 5 applications. Their migration strategy for legacy applications ranges from lift-and-shift to full rewrite.

When it comes to migration, the strategy spectrum includes rehost, re-platform, and refactor. Rehost means lift-and-shift, moving the application to a VM in the cloud with no code changes. Re-platform involves moving to PaaS with minor changes, such as using Azure App Service instead of IIS on a VM, or Azure SQL instead of SQL Server on a VM. Refactor means modernising the application architecture, splitting it into services, and adopting cloud-native patterns. The cost and risk increase from left to right, but so do the long-term operational benefits.

For .NET Framework applications, the re-platforming path is often straightforward. Azure App Service supports .NET Framework applications without code changes in many scenarios. Moving from on-premises IIS to Azure App Service, specifically the Windows plan, is low-risk for most .NET Framework 4.x applications. Additionally, Azure SQL provides a compatible target for SQL Server databases, complete with automatic backups, high availability, and no VM management. This combination can dramatically reduce operational burden with minimal code changes.

In our experience, around 80% of .NET Framework applications can be re-platformed to Azure App Service with minimal changes, resulting in a 30% reduction in operational costs. However, the remaining 20% require significant rework due to dependencies on specific Windows features or third-party libraries. For example, applications using MSMQ or COM+ components may require additional effort to migrate to cloud-native alternatives such as Azure Service Bus or Azure Functions.

Additionally, re-platforming can also involve trade-offs in terms of performance and scalability. For instance, Azure App Service has limits on the number of instances and scaling rules, which may not be suitable for applications with highly variable workloads. In such cases, using Azure Kubernetes Service or Azure Container Instances may provide more flexibility and control over scaling, but at the cost of increased complexity and management overhead.

However, there's a challenge with Windows Authentication. Enterprise .NET Framework applications frequently use Windows Authentication, which relies on Kerberos or NTLM for user authentication. The problem is that Azure App Service supports Azure AD authentication, not Windows Authentication against an on-premises AD. To migrate, you need to replace Windows Authentication with Azure AD OIDC, using App Service Authentication or EasyAuth. For applications tightly integrated with on-premises Active Directory groups and security principals, this migration requires careful identity mapping.

We have seen cases where the use of Azure AD B2C or Azure AD B2B can simplify the identity mapping process, especially when dealing with external users or partners. For example, using Azure AD B2B can enable guest user access to the application without requiring a full Azure AD license, resulting in cost savings and reduced administrative overhead. However, this approach may require additional development effort to integrate with the existing application authentication mechanisms.

The Strangler Fig pattern, introduced by Martin Fowler, offers a way to incrementally modernise a legacy application without a big-bang rewrite. New functionality is built in .NET Core, and an Azure API Management layer routes requests to either the new or old implementation based on the path. Over time, functionality can be moved from the legacy application to the new one until the legacy application can be decommissioned. This pattern reduces risk by making the migration incremental and reversible.

The key to a successful migration is understanding the trade-offs between cost, risk, and long-term operational benefits. While rehosting may be the quickest and cheapest option, it may not provide the same level of operational benefits as re-platforming or refactoring. On the other hand, refactoring can provide the most significant long-term benefits, but it also carries the highest risk and cost.

Organisations must carefully evaluate their .NET applications and determine the best migration strategy for each one. This may involve a combination of rehosting, re-platforming, and refactoring, depending on the specific needs and requirements of each application.

Ultimately, the goal of migration is to improve the application's operational efficiency, scalability, and maintainability. By understanding the migration strategy spectrum and the trade-offs involved, organisations can make informed decisions about how to migrate their .NET applications to the cloud.