A review by mrahim
Building Microservices: Designing Fine-Grained Systems by Sam Newman

4.0

This is a very good book for the domain it covers. It provides breadth into several different topics: independent deployability, API gateways, streaming, distributed transactions (sagas, two-phase commits), builds, deployments and security etc.

It summarised the business goal of microservices well: they don't reduce costs but can increase profits (microservice tax). The other goal of a microservice is to have as small an interface as possible (although size cannot be prescribed).

Independent deployability is the goal of microservices - a team should be able to have end-to-end ownership of business functionality to make changes more efficient. This involves encapsulating UI, business logic and data. This reduces effort to change business functionality and coupling of systems. Note that the goal is not high cohesion of technical functionality.

It mentions things that have since become common knowledge:
* Sharing databases is one of the worst things you can do if you wish to achieve independent deployability (unless the same team owns the systems sharing it).
* API Gateways have a tendency to become bloated with logic that belongs in code
* Avoid distributed transactions entirely if possible (even sagas), and never do 2PC due to latency and coupling.
* Client SDKs can unnecessarily couple systems and can be avoided in most cases.
* Only one artifact needs to be built and uploaded since this confirms that the artifact we deploy is the one we tested.

The section on builds was probably the highlight. Especially when it talks about how just because you may use continuous integration (CI) tools (e.g. Gitlab CI or CircleCI), it doesn't mean you are doing CI. The main questions to ask if you are doing CI or not:

(1) Do you check into mainline once per day? The less frequent, the harder future integrations become,
(2) Do you have a suite of tests to validate your changes and
(3) When the build is broken, is it top priority to fix it?

Other key points from this section:
* DORA found that merging code into mainline on a daily basis contributed to higher performance.
* Continuous deployment != continuous delivery. Continuous delivery has manual steps to verify changes even though each artifact is treated as a release candidate. Continuous deployment means that whatever is merged goes through the stages to production automatically.
* Stages of a pipeline should be (from fastest and least-prod-like to slowest and most-prod-like): local (compile and fast tests), prod-like (slow tests), performance tests and production.
* People often do smoke tests in production because of the challenges in creating a production-like environment.
* Environment-based config should live outside of the artifact itself.
* Monorepos makes more sense when org is small vs polyrepos at larger scale. It is easier to make this shift early on or the migration becomes hard. A CODEOWNERS file should be required if there is a monorepo with > 20 developers. Google's scale is different and even Microsoft created a dedicated VFS to deal with scale issues.

The section on deployments discusses how database load should be split (all writes going to a primary with other nodes designed for read-only - the latter is easier to scale). It also helped the value-add of virtualisation finally click for me rather than just dedicated servers (although Docker opened my eyes to this, it didn't fully click). The other main part here was how Kubernetes/Nomad provide Desired State Management out-of-the-box (to handle pod failures).

The section on security is interesting, one of the key highlights is knowing when to use TLS in your system vs mTLS (a user just needs TLS, but backend services in an ecosystem need mTLS). It explains the over-use of JWTs and discusses other examples, and their pros and cons.