When you're an entrepreneur with an idea for a tech startup, or a small business owner, building a skyscraper for your international headquarters, and hiring thousands of employees is not the first item on your to do list. Every investment must make sense in the context of empirical, actionable data. Any architectural style has trade-offs: strengths and weaknesses that we must evaluate according to the context that it's used. This is certainly the case with microservices. Building a distributed, event-driven, microservices architecture can seem like a building a skyscraper when compared with a normal office building-- a traditional, or "monolithic" system.
Everyone wants to build a web application with a microservices architecture ["MSA"]. MSA has even become the hammer every new project looks like. The point of this article is to try to make the case that microservices has its place. Fortunately, until you can predict that your application is going to outstrip your ability to efficiently serve your customers, your startup or small business is not probably that place. I say fortunately because, frankly, little is being said about the expense, risks, and downsides of an MSA.
I recently downloaded a e-book at no charge from redislabs.com, called Redis Microservices For Dummies®, Limited Edition which was marked "not for resale" by Kyle Davis and Loris Cro which I will make "fair use" of in this review. Several similar publications are available today, all from companies providing proprietary tools and SaaS support for MSAs.
Redis is a fine product with wide general application. What caught my attention is that they're pitching their product as a critical piece of your MSA. I then began to see several similar e-books from different software and service vendors, all of which are essentially whitepapers on how a particular product is the best fit within your MSA.
Micro Means Small. Really small! Ok?
Actually no. Microservices is a distributed systems architecture. If you don't need a distributed systems architecture, you don't need microservices. If you don't know whether you need a distributed systems architecture, you should certainly find out before you build one. Because of their inherent complexity, organizations have heretofore resorted to distributed systems architectures only out of necessity. I'll describe what I think "necessity" means and also the prerequisites for building and maintaining an MSA-- it's a big deal. It's not about just implementing some tiny little services; the actual "size" of your services is not what's important here. The following are the defining characteristics of a service in an MSA:
Focused on performing a single task (therefore, probably "small")
Aligned with a single "bounded context" from the problem domain
Independent, Autonomous, and Loosy-Coupled
Able to be scaled independently
In a MSA, the services (whatever their sizes) are supposed to be completely decoupled. That's the important thing. They don't share state. Ideally, they don't even share a database, an application server, or ports on servers.
The Monolith Architecture
The scary sounding "monolith" architecture is simply the way nearly every application or service on the internet has been designed and implemented for at least the 20 years prior MSAs becoming popular. There are few (relatively speaking) gigantic services such as Google, Amazon, Uber, Ebay, Facebook, Twitter, and some others, which absolutely need to to be designed in a completely distributed way, so that thousands of servers can handle tens-to-hundreds of thousands of requests per second. The application behind Netflix.com was once deployed as a single WAR file.
Millions of dollars have been spent by these companies in research and development, redesigning their systems so that they can scale to this level of use by the general public. For example, the average person may perform dozens of web searches on Google every day, and check their social media content several times per day. That's billions of requests these services have to handle every day without latency.
But what about everyone else? Weren't we able to get by with a web farm and a database cluster, if necessary? Wasn't it possible to scale up? The answer is "yes." We know this because every one of the largest sites mentioned earlier started out as a monolith. Just a single open source MySql database can be tuned to handle tens of thousands of read requests per second. Message queueing can be added. Some jobs can be run in batch mode during quiet hours. Algorithms can be optimized. There are many different ways to improve the performance of a monolithic architecture.
Unless you had your own datacenter, MSA was virtually unthinkable before cloud-based PaaS container-based virtualization and orchestration systems such as Docker and Kubernetes. So now that MSAs are doable, should they be done? Of course, radical decoupling to facilitate independent deployment and scaling seems like a great idea. But what are the risks or drawbacks? Not much is being said about that.
The first objectionable claim in the book is a false dichotomy-- either you have a MSA or your codebase is a single large blob of crap:
The idea that a monolithic architecture is characterized by everything being contained in "one large unit" is obviously false. Applications have always been composed of smaller modules, each ideally designed for a single responsibility. If the author really thinks that a MSA is necessary to avoid producing a "hulking, unwieldy monster," the he is either uninformed, or is cynically equivocating on the term "monolithic architecture."
Without any sense of irony, the author mentions that your monolithic architecture, should you attempt any horizontal scaling, is inherently "wasteful of resources."
Oh really? Even if this were true, I will prefer to "waste" (i.e. require more) machine resources over human resources any day of the week! Again, I get the sense that by "monolith," the author has in mind some platonic monad of a system which does not exist in reality. It's a strawman.
This book claims not only that you should "break the monolith", but you should prefer a MSA for new projects:
Regarding microservices, this is surely and almost uncontroversially a piece of disastrous advice. How are you going to get the service boundaries right without inadvertently creating a larger number of cross-service changes and overly coupled components? For new projects, you don't understand your data models well enough to do this right. And if you don't do it right, you'll pay to do it twice.
According to Martin Fowler in an article MonolithFirst, almost all the successful microservice stories have started with a monolith that got too big and was broken up.
The Microservices Alternative
There is no turning back from an MSA-- attempting to do it "halfway" is possibly worse than either a monolith or a real MSA. It's unlikely you'll be able to migrate your existing applications to a MSA piecemeal. And with this fact, one must remember that there are many more ways things can go wrong than can go right. Probably all your data models will require refactoring as you define bounded contexts according to domain-driven design principles. Services must be stateless. APIs must be versioned. Services must not call other services. Instead, you need to implement an event bus to which services will publish and subscribe. The event queue must also be outwardly scalable. Services must have a response time on the order of milliseconds, therefore all data must be cached. The data cache must be distributed.
Now in the Monolith World, many of the aforementioned characteristics of systems design are considered best practices. In the Microservices world, these become requirements. You must choose your cloud carefully, just as you used to carefully select among server hardware and operating systems because migrating dozens or hundreds of services of services from one platform such as AWS to another such as Azure could be a gradual process requiring extensive regression testing and diagnostics resources. The cost to run your services will be a function of usage. In Monolith World, your server and bandwidth costs can be constant and predictable, if theoretically inadequate.
When is a Microservices Architecture recommended?
As a distributed systems architecture, we recommend an MSA when, due to growth in the usage of your existing application, you can forecast that you will be reaching the practical limit of what can be accomplished through traditional vertical scaling and database sharding within two years. We categorically reject an MSA design for new (i.e. "greenfield") projects, especially if you don't know whether there will be large market for your system. You should carefully consider all possible alternatives including improving database performance, and the runtime and space efficiency of your existing application.
You should estimate not just the cost of reengineering your application, but also the cost of setting up new build and deployment infrastructure, as well as reorganizing teams along service lines. Your existing developers will need to acquire new skill sets, especially with regard to DevOps. Be prepared to lose some of them. There are several reasons this could be the case.
Developing, testing, and maintaining microservices presents challenges not seen in monolithic systems. They are difficult to debug-- it's especially difficult to reproduce errors, even using the best development tools currently available. Developers cannot practically load the entire system on their workstations. There are no single points of failure anywhere in the stack. Canary or red/green deployment can only be accomplished using toggle switches.
While many developers will welcome the opportunity to add new, valuable skillsets to their experience within your company, others will find these new responsibilities and challenges distracting and frustrating. In other words, development in the context of an MSA will effect productivity and morale, for better or for worse, and perhaps unpredictably.
At Lognosys, we specialize in quickly developing applications which require minimal and predictable ongoing maintenance and support. We will not present you with a finished product with hundreds or thousands of independent components, requiring a large IT staff to understand and enhance. We will, however, get your application to market rapidly. As your product accretes functionality and a large user base, we can make sure it will scale to meet your needs. If your service is winning many thousands of simultaneous users, you will still have plenty of time to properly plan, evaluate the costs, and prepare for the growth and impact to your organization.