Microsoft Teams (Microsoft)
Products & services
ASP.NET Core 3.1
Large (1000+ employees)
Microsoft Teams "MiddleTier" is an internal service that powers various scenarios in Microsoft Teams. It's one of the largest services consisting of 700+ APIs that are maintained by 10+ teams at Microsoft. Over the last two years, 50+ projects (libraries, tests, applications) under this service have been converted to .NET Standard 2.0 and .NET Core 3.1, having functional and performance equivalence (or better), and are now almost entirely running on .NET Core 3.1 in production, and looking to move to .NET 6 next. Before this migration, the service was running on .NET Framework 4.6.2 using ASP.NET Core 2.2 MVC pipeline. It runs on Azure Service Fabric with deployments in 35 Azure datacenters.
The scope of this migration was large because MiddleTier is an extra-large service in terms of the functionality that it provides with hundreds of developers that work on it every day.
The team was motivated to move to .NET Core 3.1 for the following reasons:
After migrating to .NET Core 3.1, the team has noticed the following improvements:
The following charts show comparisons between .NET Framework and .NET Core. In the future, with .NET 6, we should see even further improvements.
The overall migration was divided into three stages:
They also chose to multi-target the application to .NET Framework and .NET Core so that they would have both binaries available, and they could continue to roll out .NET Core slowly.
Their service has few OData endpoints as well along with many REST endpoints. These two shared the same routing prefix for the endpoints. This used to work fine in .NET Framework but because of routing changes, this stopped working in .NET Core. They had to move OData APIs to a different route prefix to resolve this.
The HttpWebRequest pattern with OData clients to make calls to downstream OData APIs results in higher latency compared to .NET Framework. This was due to a regression in .NET Core in which the framework doesn't cache connections. This is already resolved in newer versions of .NET.
The Azure Service Bus SDK had to be upgraded as part of this migration since the old version isn't .NET Standard compatible. The latest version of the Azure Service Bus SDK sends the request payload in JSON format whereas the older SDK sends the payload in XML format. To continue using XML payload, they had to use the DataContractSerializer.
The Service Fabric Project (sfproj) doesn't support multi-targeting inherently. They had to do workarounds in the build pipeline to produce Service Fabric packages for both target frameworks.
The older version of MimeKit can have issues with double byte characters, thus language specific validation is advised in this scenario. They uncovered similar issues when they rolled out to deployments located in Asian geography.
Every new release of .NET comes with tremendous productivity and performance improvements that continue to help accomplish our goals to build resilient, scalable, performant, and secure services. The team will continue to leverage the improvements made in .NET by upgrading to .NET 6 next.