Excellent article! The payoff for good microservices design is high, while the penalties for careless decomposition are at even higher. We’re still learning what the trade-offs are and how to best manage competing requirements.
My team has been building upon the constraints articulated by Werner Vogels at Amazon. Our approach depends on containers (currently Docker) and container orchestration (currently Kubernetes).
- Software components are built as independently deployable services packaged as containers within a Kubernetes pod.
- Each pod encapsulates the primary service container and an optimized sidecar container we call the platform proxy. The platform proxy provides the primary service with registration, discovery, read-only data buffering, logging, and synchronous (REST) and asynchronous (publish-subscribe) messaging services.
- Each pod is stateless and optimized for minimum footprint and startup time to exploit container orchestration functionality..
- All business logic in a service is encapsulated with the data upon which it acts (object-orientation).
- There is no direct access to a database from outside a service. Any and all access to a database must be accomplished by invoking a service specifically implemented to do so.
- Services publish an interface that enables access to its data and functionality by other services. Use of Representational State Transfer (REST) is an appropriate style for such interfaces.
These constraints contribute to location transparency, efficient failover, performance, reliability, and robustness — but require intelligent decomposition to work well.