Whether you love the concept of microservices or, you're still trying to wrap your head around them like I am, there's no denying that the world of web development appears to be moving in the direction of smaller, more independent, and more distributed application architectures. Most of the books, articles, and presentations about microservices that I've seen attempt to sell you on the value-add of microservices. But, Production-Ready Microservices by Susan J. Fowler doesn't really do that. Instead, she assumes that you've already bought into the vision of microservices; and, as such, spends the majority of her book talking about the world of hurt that microservices can bring down upon your team if you don't approach them seriously. Production-Ready Microservices is, essentially, a list of everything that can go wrong; and, a high-level overview of how you can setup your microservices - and your team - for success.
One of the things that I appreciated most about this book is the frankness with which Fowler talks about the complexity and the cost of microservices. Rather than selling microservices as a silver bullet, she clearly explains that they are not for everyone. Only companies with enough resources can afford to develop, staff, and maintain microservices the right way:
Small companies often do not have the necessary infrastructure in place to sustain microservices, even at a very small scale: good microservice architecture requires stable, often very complex, infrastructure. Such stable infrastructure requires a large, dedicated team whose cost can typically be sustained only by companies that have reached the scalability challenges that justify the move to microservice architecture. Small companies simply will not have enough operational capacity to maintain a microservice ecosystem. Furthermore, it's extraordinarily difficult to identify key areas and components to build into microservices when a company is in the early stages: applications at new companies will not have many features, nor many separate areas of functionality that can be split appropriately into microservices. (Susan J. Fowler)
And, while developers should always be responsible for their code, even in the context of a monolith, this responsibility is greatly amplified with microservices because information about how things work becomes much more decentralized. Since each team is working on a different set of microservices, there's no longer the same level of tribal knowledge that you can have in a monolith:
With a monolith, an operations organization can easily be staffed and on call for the application, but this is very difficult to achieve with microservice architecture because it would require every single microservice to be staffed by both a development team and an operational team. Consequently, microservice development teams need to be responsible for the operational duties and tasks associated with their microservice. There is no separate ops org to take over the on call, no separate ops org responsible for monitoring: developers will need to be on call for their services. (Susan J. Fowler)
Of course, after setting the appropriate expectations about the complexity of microservices - both developing and maintaining - Fowler also paints monoliths as having their own set of problems.
The complexity of the application is growing steadily, and hundreds (if not thousands) of tests must be written in order to ensure that any change made (even a change of one or two lines) doesn't compromise the integrity of the existing thousands upon thousands of lines of code. Development and deployment become a nightmare, testing becomes a burden and a blocker to the deployment of even the most crucial fixes, and technical debt piles up quickly. (Susan J. Fowler)
Fowler is not the first author to describe this end-of-days scenario of monolith development. But, it's not really a vision that I have ever connected with emotionally, which might be why I have some trouble wrapping my head around microservices. At InVision, I basically work on a monolith. And, I really don't feel the kind of pain that many people associate with the development and maintenance of a monolith.
Now, you could argue that I have a skewed perspective because I've been working here since the company was founded and I have a lot of tribal knowledge. But, that would completely discount the large number of people who have since joined and have successfully worked on the monolith, in most cases having no prior knowledge of the programming language it was written in. And yet, the world doesn't end and the app doesn't explode, despite the fact that the monolith has fewer unit and integration tests than any of our microservices.
And, yes, we deploy the monolith many times per day.
But, I've digressed - Production-ready Microservices isn't a book about why you should use microservices, it's a book about how you and your team should approach microservices in order to be successful. And, to that extent, I think Fowler does a great job. She breaks "production readiness" down into several macro areas and then digs into each area, looking at all the things that can possibly go wrong or be implemented poorly, sharing her experience as a Site-Reliability Engineer (SRE) at Uber and other smaller organizations.
While Fowler keeps the conversation high-level in terms of technology, she is exacting in her approach to understanding systems: everything can and should be measured. CPU usage, RAM usage, throughput, response times, traffic patterns, error codes, queue sizes, etc. Nothing about the way in which a microservice operates should be "fuzzy" or left up to one's gut instincts. A measured system is the only system that can be truly understood and prepared for the future.
And, a measured system is the only system that be fully automated. With normal, warning, and critical thresholds applied to each measured value, everything from alerts to rollbacks can be automated. One of the biggest points of failure is "human error;" and, anything that can be scripted and executed by a machine, should be.
To be honest, I found this book rather intimidating. The level of sophistication and investment needed to run a "proper" microservices ecosystem seems staggering. When I read about technology, I often envision myself as the sole implementor of said technology. But, managing a microservice-based ecosystem appears to necessarily be a team-endeavor. So, it's not really surprising that the book is a bit overwhelming, especially for someone like me who is more "code monkey" than "operational engineer."
As a final note, one more aspect of the book that I enjoyed was Fowler's dispelling of some myths about microservices; in particular, the freedom and independence that is often a large selling point of microservice-based development:
Microservices infamously come with the promise of greater developer freedom, freedom to choose whichever languages and libraries one wants. This is possible in principle, and can be true in practice, but as a microservice ecosystem grows it often becomes impractical, costly, and dangerous. (Susan J. Fowler)
As a software engineer, I enjoyed this book for its insight into systems thinking. And, for how it can help me think about hardening my own software against failure. But, I think the book might be more valuable for actual site-reliability engineers and other operational engineers. If nothing else, this book removes all doubt about the complexity of a microservices approach to software; and, demonstrates that there is light at the end of the tunnel if you have the right team and the necessary organizational buy-in and the money and time to dedicate to doing things correctly.