
With the Microservice revolution now in full swing, I thought it would be an interesting idea to catalog a few reasons (or scenarios) where adopting the platform might not make the most sense.
Hey, I get it, we all want the latest and greatest, but if we've learned anything from the lessons of web services, WS*, and ESB mania, we should probably take stock before just blindly plunging ahead. Before we start, however, I want to be clear; Microservices are my preferred architecture and provide a tremendous long-term benefit for the enterprise. We've all heard the value proposition:
- Loose coupling
- Surgically scalable
- Enhanced development productivity
- Alignment with domain-driven design (DDD)
- Extensibility
- More agile enterprise
To name a few.
I've seen many organizations benefit from this architecture. They've seen real business and strategic value from the flexibility, extensibility, and scalability their microservice-based platforms provide.
I've also seen a few not-so-great case studies.
I thought it might be interesting to do a personal inventory and come up with a top three. Some of this will fall into the "don't-ask-me-how-I-know-this" category, but there's also a lot of emergency room triage knowledge sprinkled in as well.
1. It can be expensive
Yup, that's correct. Not going to sugarcoat it, it is expensive to develop enterprise systems based on microservices.
Don't get me wrong, a well-designed service platform can make things that used to be extremely complex seem almost trivial, however, that elegance comes with a price. Finding and staffing a team of developers that have a meaningful understanding of messaging architectures, advanced data storage concepts, complex patterns (e.g. CQRS, Event Sourcing, etc.), and advanced topics like Domain Driven Design is not an inexpensive proposition.
Let's also add the cost of DevOps (budget at least 2x what you did for your average monolith), hosting a platform with a mountain of moving parts in the cloud (with multiple environments!), and the general inefficiencies of teams working on disparate domains, while still expecting a seamless user experience. Also consider the inefficiencies of bug remediation and testing in a distributed platform and the costs begin to pile up.
For organizations that have complex application requirements that need a lot of extensibility, flexibility, and future-proofing, the additional development and support costs are usually more than worth the additional spend. The long-term benefits of microservices for larger platforms are hard to ignore and usually worth the price of admission. Even mid to small projects can benefit with some pragmatic design-thinking, however, making sure the business has realistic expectations of project cost will be crucial to ensure you get a second microservice project to work on.
2. It's often overkill
I know the sad old monolithic architecture is everyone's favorite punching bag these days. It's gotten to the point that if you actually design an application in this manner, you feel as though you're doing something wrong. Well, you aren't. Not always anyway.
There are plenty of scenarios where a good old-fashioned monolithic application is probably the most cost effective and pragmatic approach to a business problem. Rolling out a multi-service, event-driven architecture using domain events and event sourcing databases for your upcoming book club seminar registration database, while fun, is probably not a good place to stick your toes in the water, and you'll quickly find yourself in the deep end of the pool. You might stick with a traditional MVC-omatic templated app for that one.
There are also times when microservices just don't make sense. There may just be no way to split up business logic into a subset of services cleanly without so much functional service coupling that it becomes a monolith. Maybe your application will not be around very long. Why go through the trouble of implementing and managing all those cloud assets for something that will disappear in a year? Or maybe your domain is static and never changes. Why bother with microservices if you don't need the flexibility that the pattern affords over time?
Yeah, but Netflix!
You are not Netflix (most likely), so why introduce all that complexity into your life when it is completely unnecessary. Sure, it'll be fun for a while, but soon you'll have to support it while your have other, more important issues stacking up on your desk.
3. The complexity can overwhelm you
If there ever was an application for Ron Burgundy's famous quote - "well, that escalated quickly!" - it is in the practical implementation of some microservice platforms. For most of us, our introduction to the microservices world is a utopian vision where services are like independently operated fast food restaurants that abstract complexity into well behaved fiefdoms that can be managed, upgraded, refactored, and released with little or no impact to the ecosystem.
In practice, this doesn't usually hold true. Functional Coupling (the unintended incidental coupling of services due to business functional requirements) usually rears its head early and often, ensuring that product features that satisfy business requirements require complex choreographies that involve multiple services. This essentially creates a monolith, and not in a good way (yes there are good ways!).
You can avoid this complexity by insisting that the software do nothing, for no one, forever, but I have not had a much luck with that approach.
The other inevitable complexity of a microservices architecture is that it is difficult to do correctly. There are a lot of anti-patterns. In fact, most of us who have implemented a microservices architecture have firsthand knowledge of some or all of them. To name a few:
- Static message contracts
- Distributed monolith (shared persistence)
- Cross service query stitching
- ESB usage
- Shared libraries
- Megaservice
- Local logging
- Local configuration
- Anemic DevOps
And that's just to name a few.
Complex, distributed architectures are hard and using best practices means implementing a lot of unavoidable complexity that most of us are not going "get" until we understand why we should pay attention.
Pragmatic thinking is your friend
One of the most frequent questions I get is whether creative pragmatism can reduce some of the complexity when implementing a microservice architecture. The answer is yes! But the question is flawed. Pragmatic thinking is important and can be useful in reducing complexity, but it should be applied BEFORE you begin design. The benefits of pragmatism are reaped in the "what architecture" phase, and not in the "how to architecture" phase.
There is no other architecture that exemplifies the expression, "in for a penny, in for a pound" more acutely than microservices. Once you commit, you must follow best patterns and practices or you'll end up creating something with all of the flaws of its predecessors that costs twice as much to support and takes twice as long to upgrade. In other words, your architecture is providing negative business value.
Nobody likes negative business value.
Again, I'd like to stress that the microservices architecture revolution is real. And these patterns provide exceptional business value when applied judiciously to the correct problems; it's just important that you know what you're getting yourself into before making the commitment.