Leveraging microservices for your business, Part 1: Why microservices matter
Microservices has been gaining a lot of interest within the commerce industry; and many developers have already started experimenting with them. However, before you adopt microservices for your business you must understand what they are and why they matter.
Principal Architect, Matt Bishop lays down the groundwork to help organizations and developers determine if microservices are right for business. In this series he’ll outline what processes and practices are needed to support microservices, in addition to the benefits and difficulties of a microservice architecture.
What are microservices?
This question turned out to be surprisingly hard to answer, mostly because people writing about microservices describe them as implementation details like Docker containers, NoSQL databases, REST and other technologies. Some definitions are great, yet employ somewhat vague language to define them. For instance, Chris Richardson at microservices.io calls them: "highly maintainable", "loosely coupled", "independently deployable" and "organized around business capabilities." Some of these can easily be dug into and worked with, like “loose coupling” and “independent deployment”; however, the other aspects are really hard to measure, such as “maintainability.”
A favorite definition comes from Adrian Cockroft where he defines microservice architecture as:
“Loosely coupled service-oriented architecture with bounded contexts.”
This definition is favored because every part of the statement is understandable and identifiable. You can take a system, measure it against these qualities and determine if they are indeed microservices.
Now let’s break this definition down to discover what it means.
This quality is a mainstay in service-oriented architectures. It means that the components in a system should share as little as possible with each other. System cohesion demands that the components provide coordinated, useful services to fulfil the business' requirements, yet this quality encourages each component to require as little as possible from each other. The key benefit of loose coupling is replaceability. You can replace a component with another version and not disrupt the system overall.
The most minimal coupling between components is a shared business identifier. Customer name, account number, invoice number, and other human-readable identifiers knit the business together in the physical world. In the same way minimally-coupled microservice components share these same identifiers with each other, but not much else. These components do not rely on each other for data and instead store their own state internally rather than rely on other components to provide seemingly-shareable data.
For instance, you would not find an "address" service that stores addresses for other components. Instead each would store their own relevant addresses locally to avoid coupling across components. The component can choose to modify this address, or store only relevant portions of it (like country) without worrying about impacting any other component. It turns out that bounded contexts often have data that looks and sounds similar to other contexts, but that is usually a coincidence.
The least-favorite part of Adrian's microservices definition, mostly because the concept of "service-oriented" has been applied to so many things over the decades it has lost its true meaning. Anyone approaching this term will likely have a definition that will conflict with "loosely coupled." This is because “services” are meant to provide data and capabilities to other services so they will not have to manage the capability themselves. In microservices, "service-oriented" covers a few different kinds of orientations.
One orientation for a microservice is proxying a capability in another external system. A shipping microservice can proxy capabilities from external shipping services like UPS for example. The consumer of the shipping service will have a shared identifier (say order number) that is used internally to find the correct service and tracking number for the shipments. The external service is queried for status, which is returned to the caller as data.
A microservice can be oriented to providing a direct business capability. An "order" microservice is one that holds orders for the business. Rather than proxying to an external order system, this microservice stores the data and business rules internally and offers up order management as a standalone service. If this feels like a vague definition, further clarity will come in the Bounded Context part below.
Another orientation is coordinating workflow between services. Proper loose coupling means two services cannot directly know about each other. Like foreign dignitaries at a meeting, they need someone to coordinate their introduction and communication. They do not speak each other's language and only respond to the coordinator/interpreter. This analogy isn't quite right, as the two dignitaries do know each other and intend to communicate directly. In microservices, the two services cannot know they are being coordinated. That knowledge rests with the coordinator.
There may be other types of service orientations, but these three are favored as they tie together the business purpose of the architecture and integrate it into the IT topology the system must live within.
How do you know your microservice is the right size? Is it too small, is it too hot? You can probably recall the tale of Goldilocks and the Three Bears, where she found comfort in the food and furnishings that were "just right". This sort of intuitive scoping protocol is not recommended for your microservice designs. Bounded contexts are discoverable using proven techniques from Domain-Driven Design.
It's hard to measure culture, but one-point sticks out. A bounded context's data model is internally consistent, which means changes to the data in that model must be consistent for all the data in that model. You cannot have contradictions in the bounded context's data. The standard way of achieving this is to use persistence transactions in a shared database. In microservices an individual service will maintain a transactional database of its context's state and share data internally.
Microservices should not share a data storage system with another service because information will leak into the services that share the data store, and this data sharing will break the loose coupling needed to maintain independence.
Check out Part 2, where Matt reviews the benefits and difficulties with microservice architecture.