What Is Strangler Fig?
The Strangler Fig pattern (named after the strangler fig tree that gradually surrounds and replaces a host tree) is a strategy for modernizing legacy systems step by step. Instead of a risky full rewrite of the entire system at once, we replace old functionality with new functionality gradually, while the system continues to work.
Practical Case: Migrating ASP.NET MVC to ASP.NET Core
Imagine we have an old application on .NET Framework 4.8. Rewriting everything at once is too risky. Instead, we use the Strangler Fig pattern.
Here is our starting point: a standard legacy controller directly accessing the business service.
namespace LegacyMvcApp.Controllers
{
public class LegacyOrdersController : Controller
{
public async Task<ActionResult> Details(int id)
{
// Old direct dependency
var ordersService = new OrderService();
var order = await ordersService.GetById(id);
if (order == null)
{
return HttpNotFound();
}
return View(order);
}
}
}
Step 1. Set Up a New ASP.NET Core API
First, we create a new API. This API will contain the modern business logic and independent controllers.
[Route("api/[controller]")]
[ApiController]
public class OrdersController(IOrdersService ordersService) : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<Order> Get(int id)
{
var order = ordersService.GetById(id);
if (order == null)
{
return NotFound();
}
return Ok(order);
}
}
Step 2. The Old MVC Starts Calling the New System
The legacy controller stays in place, and the routes work exactly as before. However, inside the controller, the request is now redirected to the new ASP.NET Core API.
In a production environment, it is better to use
IHttpClientFactoryrather than creating a staticHttpClient.
public class LegacyOrdersController : Controller
{
private static readonly HttpClient _httpClient = new HttpClient();
private static readonly string _newApiBaseUrl =
ConfigurationManager.AppSettings["NewApiBaseUrl"];
public async Task<ActionResult> Details(int id)
{
var url = $"{_newApiBaseUrl}/api/orders/{id}";
// Call the new API to get the order details
var response = await _httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var order = JsonConvert.DeserializeObject<Order>(json);
if (order == null)
{
return HttpNotFound();
}
return View(order);
}
return new HttpStatusCodeResult((int)response.StatusCode);
}
}
By doing this, the UI does not change and the URLs remain the same, but the functionality now lives in Core.
Advantages of the Approach
-
Gradual process. We move functionality one endpoint at a time.
-
Minimal risk. The old logic remains available as a fallback option if needed.
-
Testing in real conditions. The new API works immediately under real load but in a controlled mode.
-
No downtime. Users do not notice the migration process.
What Happens After Moving the Backend?
When the entire API is already running in .NET Core, you can start the next phase. The old MVC Views are replaced one by one with a modern frontend (React, Vue, or Angular). The old system gradually shrinks, and finally, only the new architecture remains.
Conclusion
The Strangler Fig pattern is the safest way to modernize outdated .NET applications. It allows you to move logic to ASP.NET Core gradually and painlessly, maintaining stability and control at every step.