Do you REALLY need Microservices?
That Developer Dad
2024-07-21
This is a bit of a Hot Take, but I don't think you need to be considering this architecture right up front. Most of the time.
Do I really need microservices?
Maybe? Probably not, but honestly, “It Depends™“. I’ll answer your question with a question of my own.
Why do you think you need to do microservices?
”I read about it on social media/trade magazines/some giant company.”
I call this Cargo-Cult-Driven-Development (CCDD) and it’s rarely a valid reason for such a tectonic shift in your architecture AND development practices. “If GoogFlix and MicroBook jumped off a bridge, would you do it too?"
"My development team says we need to stay current.”
This one is likely because of Resume-Driven-Development (RDD), which is ALMOST as bad a reason as CCDD, but it does show a hunger for growth among your team members, so maybe work with them and get creative. Find a way to explore the idea without derailing all the work you’re being paid to do.
”The app is slow and getting slower, and it’s hard to maintain.”
This might show a need for careful decomposition.
”I’m building a new app that needs to do some of the same things as my current app.”
This could justify splitting things out, but let’s not be hasty. Distributed Applications add some hefty challenges.
Challenges of Microservices:
- Deployment Complexity:
Instead of deploying one unit, you’re dealing with multiple pieces simultaneously. This requires automation and DevOps practices.
- Need for CAREFUL Abstraction:
You need to get your abstractions correct before pulling your codebase apart. This often requires an application architect.
- Increased Cognitive Load:
Microservices require improved observability, security considerations, and deployment strategies that you might not be used to.
What about an alternative? The Well-Factored Monolith:
Instead of jumping straight to microservices, consider a well-factored monolith.
This approach involves:
- Compose your monolith as if it’s a distributed system
Get good at those abstractions.
- Define clear boundaries between components
Get good at determining and enforcing domain boundaries.
- Set up patterns for inter-component communication
Add observability, improved validation, and APIs between your components now.
Start doing those things, and you’ll see these things emerge:
- Ability to iterate on parts without affecting the whole system
You’ll still need Big-Bang deployments, but the testing scope can be reduced.
- Easier distribution of responsibilities among smaller teams
When things are well defined and separated, different groupd can work in different parts of the application without merge conflicts.
- Improved testability of individual components
If only one part of the application changed, only the parts that are affected need to be tested.
- Flexibility to extract services later if needed
If your internal components are kept independent of each other, you can split them out and replace a concrete implementation with a service proxy pretty easily.
When to Consider Breaking the Monolith:
- High levels of code churn within a component:
If a part changes much more often than the rest, it might be a candidate for extraction.
- Significant code duplication:
Consolidate shared code, but be prepared for divergence over time.
- Need for separate process spaces:
Some activities might benefit from running in their own process, such as long-running tasks or those accessing limited resources.
Conclusion:
Microservices can offer benefits, but they come with significant challenges. Start with a thoughtful, resilient, and composable application architecture strategy. The well-factored monolith provides a solid foundation, allowing you to evolve your architecture as needed.
Remember, distributed systems bring their own complexities in troubleshooting, state management, and security. Ensure your team is prepared for these challenges before making the leap.
The bottom line: A poorly factored Monolithic Application WILL become a Giant Ball of Mud. A poorly factored Microservice Application devolves into the Painful Tangle of Barbed Wire. It’s all about the internal component design, and your team’s commitment to protecting that design.