|
| 1 | +--- |
| 2 | +title: NServiceBus and Strangler Fig |
| 3 | +summary: Legacy Modernization with NServiceBus and the Strangler Fig Pattern |
| 4 | +reviewed: 2025-05-12 |
| 5 | +--- |
| 6 | + |
| 7 | +For teams maintaining legacy .NET systems, modernization can feel daunting. Rewrites are risky, and big-bang migrations rarely go to plan. An alternative approach involves introducing the [Particular Platform](https://particular.net/platform) into a legacy environment using the [Strangler Fig pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig). |
| 8 | + |
| 9 | +## Establishing the façade |
| 10 | + |
| 11 | +The process begins by placing an API façade between the frontend and the existing backend. For example, the backend might be an [ASP.NET](http://asp.net/) MVC application running on .NET Framework 4.8, with a frontend built using Angular.js or Knockout.js. The frontend remains unchanged at this stage. The façade is developed in modern .NET (currently .NET 9) and becomes the new single entry point into the system. |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +At this stage, the system still functions as a tightly coupled monolith. Introducing the façade provides a clean boundary, enabling evolution without disrupting the client or core business operations. |
| 16 | + |
| 17 | +## Introducing the Particular Service Platform |
| 18 | + |
| 19 | +The next step involves integrating the Particular Service Platform into the façade. At the heart of the platform is NServiceBus, which enables reliable message-based communication between endpoints. Messages—simple C# classes—are sent between endpoints to trigger actions, model workflows, or propagate events. The façade can now publish or send messages without migrating any underlying functionality. |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +### Platform capabilities and initial benefits |
| 24 | + |
| 25 | +By introducing the Particular Service Platform at the API façade level, the system gains several operational benefits immediately—even before any business functionality is migrated: |
| 26 | + |
| 27 | +- **Reliability & resilience**: Messages are durably stored, automatically retried on failure, and protected from data loss. The system can recover from transient failures without manual intervention. |
| 28 | +- **Observability & diagnostics**: ServicePulse and ServiceInsight offer out-of-the-box observability tools. ServicePulse enables near real-time monitoring and recovery operations (such as retrying failed messages), while ServiceInsight provides rich visualizations, message flows, and debugging insights for developers. These tools provide visibility into system behavior often absent from legacy applications. |
| 29 | +- **Backpressure & decoupling**: Queues absorb spikes in load, and messaging decouples producers and consumers, reducing direct dependencies on the legacy system. |
| 30 | +- **Error handling**: Failed messages are routed to an error queue and can be retried once the issue is resolved. While this does not eliminate failures in the legacy app, it improves transparency and recovery. |
| 31 | +- **Operational safety**: New logic can be introduced into the façade or new services with reduced risk, enabling safer, incremental delivery. |
| 32 | + |
| 33 | +Even without migrating a single feature, this architectural shift introduces durable messaging, diagnostics, and built-in failure recovery. These capabilities establish a foundation for safe, confident evolution over time. |
| 34 | + |
| 35 | +## Migrating functionality |
| 36 | + |
| 37 | +With messaging in place, new components can take on specific responsibilities outside the legacy system and evolve independently as needed. Whether the target architecture is a monolith, modular monolith, microservices-based system, or something in between, the messaging foundation supports a range of styles without prescribing a specific direction. The legacy system continues to support remaining responsibilities, but boundaries are now clearly defined. |
| 38 | + |
| 39 | + |
| 40 | + |
| 41 | +### Intermediate benefits |
| 42 | + |
| 43 | +As business logic moves into new services, the benefits compound: |
| 44 | + |
| 45 | +- **Performance & scalability**: Individual workloads such as order processing or billing can scale independently. Asynchronous messaging avoids blocking client requests. |
| 46 | +- **Autonomous services**: Services become independently deployable units, versioned and tested in isolation. |
| 47 | +- **System evolution**: New services are built using modern frameworks and hosting models (e.g., .NET 9, containers), without requiring upgrades to the legacy stack. |
| 48 | +- **Cleaner boundaries**: Messaging introduces explicit contracts between services, clarifying responsibilities and dependencies. |
| 49 | +- **Safer experimentation**: New features can be released gradually using feature flags or by running new implementations in parallel (e.g., shadow reads). |
| 50 | + |
| 51 | +## Fully modernized system |
| 52 | + |
| 53 | +Over time, more features move into independently hosted services, and eventually the legacy backend is retired. |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +The client remains unaware of internal changes, while the system becomes progressively more modular, observable, and resilient. At this point, the legacy backend has been fully decommissioned, and all functionality is handled by a modern, message-driven system. |
| 58 | + |
| 59 | +The API façade may then be removed entirely, especially if no longer required for routing or compatibility with the legacy system. Alternatively, it may be retained as an API gateway to provide a centralized entry point for cross-cutting concerns such as authentication, authorization, request throttling, logging, versioning, or telemetry. Whether the façade is removed or evolves into an API gateway depends on specific system requirements and architectural direction. |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +### Useful links |
| 64 | + |
| 65 | +For more information, see the following resources: |
| 66 | + |
| 67 | +- [Strangler Fig Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig) |
| 68 | +- [Particular Platform Overview](/platform) |
| 69 | +- [NServiceBus Documentation](/nservicebus) |
| 70 | +- [ServicePulse Documentation](/servicepulse) |
| 71 | +- [ServiceInsight Documentation](/serviceinsight) |
0 commit comments