Chapter 84. Trade-Offs in a Microservices Architecture
Is there an optimal software architecture? What does it look like? How do we measure “optimal” when it comes to building and operating software? An optimal software architecture is one that has maximal flexibility for change at the lowest possible cost. Here, cost is measured in terms of certain qualities that represent a software architecture’s design and implementation—in addition to the cost of the infrastructure to operate it. The defining trait of a software quality is that it can be tangibly measured and has an impact on other qualities.
For example, if a software architecture requires strong consistency guarantees, there is an impact on qualities like performance and availability. Eric Brewer created the CAP theorem to describe a set of measurable trade-offs where you can only choose two out of three guarantees for running a database: consistency, availability, and partition tolerance. The theorem states that when applications share state across the boundaries of a network, you must choose between consistency or availability, but you cannot have both.
One of the main problems with microservices is that there is no single comprehensive definition. Moreover, microservices are a collection of concepts and ideas that are based on a set of constraints for delivering a services architecture. A microservice, or any piece of software you build, is a history of choices—which will affect your ability to make new choices today.
Organized around business capabilities
Database per service
One application, one team
As you go out into the world of software development, you will eventually find that there is no such thing as the right choice. Indeed, most developers or operators might believe there is a best choice, and you may find that they argue strongly in favor of that choice. As you encounter more and more opportunities to make a decision between multiple choices, for instance, which database to use, you’ll eventually come to discover that all available options introduce certain trade-offs. That is, you will usually have to lose something to gain something.
|Availability||How often is my system available to its users?|
|Performance||What is the overall performance of my system?|
|Consistency||What guarantees does my system provide about consistency?|
|Speed||How fast can I deploy a single line of code change to production?|
|Composability||What percentage of an architecture and codebase can be reused instead of duplicated?|
|Compute||What is the cost of my system’s compute under peak load?|
|Scalability||What is the cost of adding capacity if peak load continues to increase?|
|Marginality||What is the average diminishing marginal return of adding developers to my team?|
|Partition tolerance||If a partition in the network causes an outage or latency, will my application experience or cause a cascading failure?|
How does answering one question affect answering the others?
You will find each of these questions often has some kind of relation to the other questions. If you ever find yourself making a tough decision in a software architecture that uses microservices, come back to this list of questions.