generate a new title here, between 50 to 60 characters long
Written on
Chapter 1: Understanding the Need to Split a Monolith
There are various motivations behind the decision to decompose a monolith. Common reasons include the desire for independent scalability, enhancing the modularity of the codebase, and mitigating the noisy neighbor issue. Regardless of the motivation, this undertaking carries inherent risks. You're essentially either migrating existing code or rewriting parts of it—sometimes a combination of both. The objective is to maintain the current functionality for users while navigating these complexities. Compounding the challenge, much of this code may be outdated, and current developers often lack the context regarding its original purpose. As a result, there's a risk of ending up with a system that remains just as intertwined as before, yet now suffers from delays associated with service calls in a distributed architecture.
Getting Started
Before embarking on the journey to dismantle your monolith, it's crucial to carefully evaluate your service architecture and define your domains. This consideration will aid in team assignment and ownership, while also helping to prevent the previously mentioned distributed monolith scenario.
Next, you'll want to determine whether to adopt a Big Bang approach or a Strangler Fig method. Briefly, the Big Bang approach replaces everything at once, offering the advantage of comprehensive flexibility in rewriting and potentially removing features altogether. While this method may be quicker to implement, it demands your full attention throughout the process.
Conversely, the Strangler Fig approach begins with the least tightly coupled components, progressively removing them until the monolith is completely divided. This method allows for faster realization of benefits, presents lower risk at any given moment, and is often more palatable to upper management, as it permits ongoing development of new features while the transition occurs in the background. Conversations with various professionals suggest that the Strangler Fig method is the more popular choice among organizations.
Assuming you opt for the Strangler Fig route, the next step is to select which services to begin with. Ideal candidates include those less dependent on other components, services that are likely to be modified anyway, entirely new functionalities, and foundational services that other services rely on (such as Authentication, Authorization, or API Gateway). Additionally, any functionality that needs to scale at a different rate or is currently problematic should be prioritized. The more criteria a service meets, the better suited it is to be your starting point.
Minimizing Your Move
Before attempting to migrate or rewrite your code, ensure that you’re not carrying over unnecessary components. At a high level, implement feature flags to encapsulate log statements, allowing you to determine which parts of the codebase remain in use while minimizing log generation.
Splitting Out a Service
Once you've chosen a service to work on and eliminated redundant code, a typical starting point is to create an interface that aligns with your envisioned new service on top of the existing one. While you may already have effective APIs, you might find opportunities to enhance them, making this an ideal time for updates.
Next, develop your new service while maintaining the same interface. This step is crucial as it enables seamless traffic routing between the existing monolith and the new service without requiring client modifications.
Testing Your New Service
Maintaining a consistent interface not only facilitates a smoother transition but also sets the stage for various testing methodologies, including parity, load, and stress testing. Load testing ensures that the new system can manage expected traffic levels, while stress testing identifies its breaking points. Parity testing compares outputs from both systems to verify that the new implementation aligns with the old, ensuring no features are lost in the transition. All three testing types are essential for mitigating risk during the migration to a new service, and can be efficiently conducted using feature flags.
In the video titled "How Feature Flags Can Make Splitting a Monolith Safer," Joy Ebertz discusses how feature flags can facilitate safer transitions when deconstructing monolithic applications.
Another insightful video, "Feature Flags In .NET + How I Use Them For A/B Testing," explores practical applications of feature flags in .NET environments, particularly for A/B testing purposes.