In just 20 years, software engineering has shifted from architecting monoliths with a single database and centralized state to microservices where everything is distributed across multiple containers, servers, data centers, and even continents. Distributing things solves scaling concerns, but introduces a whole new world of problems, many of which were previously solved by monoliths.

The move towards distributed architectures brings lots of benefits: easier testing, smaller deployable units, looser decoupling, smaller failure surfaces, to name a few. But it also brings its own set of challenges. How can a set of services evolve together in a way that doesn’t break the system?
