Case Study: Service Templates
Microservices architectures are designed to be share nothing architectures — each component is as decoupled as possible from other components, adhering to the bounded context principle. However, the shunning of coupling between services pertains primarily to domain classes, database schemas, and other coupling points that harm the ability to evolve. Development teams often want to manage some aspects of the technical coupling uniformly — adhering to our remove needless variables advice — to ensure uniformity.
For example, monitoring, logging, and other diagnostics are critical in this architectural style due to the profusion of moving parts. When operations must manage thousands of services, when service teams forget to add monitoring capabilities to their service the results can be disasterous. Upon deployment, the service will disappear into a black hole, because in these environments, if it can’t be monitored, it is invisible. Yet, in a highly decoupled environment, how can teams enforce consistency?
Service templates are one common solution for ensuring consistency. These are preconfigured sets of common infrastructure libraries like service discovery, monitoring, logging, metrics, authentication/authorization, and so on. In large organizations, a shared infrastructure team manages the service templates. Service implementation teams use the template as scaffolding, writing their behavior within. If the logging tool requires an upgrade, the shared infrastructure team can mange it orthogonally from the service teams — they should never know (or care) that the change occurred. If a breaking change occurs, it fails during the provisioning phase of the deployment pipeline, alerting developers to the problem as soon as possible.
This is a good example of what we mean when we espouse appropriate coupling. Duplicating technical architecture functionality across services creates a slew of well-known problems. By finding exactly the level of coupling we need, we can free evolution without creating new problems.
Use service templates to couple just the appropriate parts of architecture together — the infrastructure elements that allow teams to benefit from coupling.
Service templates exemplify adaptability. Eliminating the technical architecture as the primary structure of the system makes it easier to target changes to just that dimension of architecture. When developers build a layered architecture, change is easy within each layer but highly coupled across layers. While a layered architecture partitions the technical architecture parts together, it entangles other concerns like domain, security, operations, etc. By building a part of the architecture solely for technical architecture concerns (e.g., service templates), developers can isolate and unify change to that entire dimension. We discuss how to think about architectural elements as deployable units in Chapter 4.