Design Independent Microservices
Independent microservices allow you to scale your development workforce while maintaining agility and a rapid development pace. Well-designed microservices have the following attributes:
- Independent lifecycles – Teams must be able to develop, deploy, and make technology choices for their microservices without involving other services or teams. Starting, stopping, or changing a microservice should not interrupt other services.
- Stable interfaces – Microservice interfaces must not break during updates. If incompatible changes to an interface are required, they should be implemented by versioning the interface.
- Asynchronous communication – A microservice needs to communicate with other services, but the peer might not be available immediately. Asynchronous communication via messaging can remove dependencies on the availability of other services.
- Resilience and fault tolerance – A microservice should still run if other services in the system cause problems.
- Graceful degradation – If one microservice fails, the rest of the system should still function as best as possible (e.g., falling back to a default flow).
- Independent scalability – Each microservice should have access to the resources needed to respond to changes in system load without impacting other services.
- Local data storage – Each microservice should store a local copy of the data needed to fulfill its task.
Align Microservices to the Business Domain
Organizations often struggle to implement microservices that support an end-to-end business process while maintaining independence and preserving development team autonomy. For example, imagine that you have a fulfillment process for online orders of digital goods. It requires microservices such as payment, inventory, shipping, and so on. Although each service operates independently, the order fulfillment process requires a logical chain of events like the one shown in Figure 1.
Figure 1: Example of an order fulfillment process
In this scenario, an appropriate solution is to align a single order fulfillment microservice with the business need to fulfill digital orders. This microservice would be independent because it would coordinate all tasks required for an order: retrieving customer payments, fetching digital goods, and so on. This approach also preserves team autonomy because one team can develop, deploy, and redeploy the order fulfillment microservice on their own.
Balance Choreography and Orchestration
Microservices are often associated with the concept of event-driven communication. An event is something significant that happens in a system (e.g., a customer places an order). When communication is event-driven, services emit events without knowing which other services will pick them up. Services also react to events without knowing where they came from. Each service simply subscribes to topics that are relevant to its purpose and receives a notification when an event related to that topic is emitted. Event-driven communication between microservices is known as “choreography.”
Event-Driven vs. Command-Driven Communication
Event-driven communication allows a high degree of independence for microservices and autonomy for development teams. However, it poses a challenge because, as described earlier, many business activities require a logical chain of events. The event chain manifests as a series of event subscriptions that implement a logical flow; however, it is not explicitly defined anywhere, making it hard for people to understand, monitor, and troubleshoot the large-scale flow of activities.
Command-driven communication is a different approach through which a service can instruct another service to take an action. The recipient can accept or reject the command, but it cannot ignore it. In contrast to event-driven communication, the sender knows which service will receive its command. Command-driven communication between microservices is known as “orchestration.” This approach lets the microservice that implements the flow of business activity control the actions and timing of other services, thus maintaining an overview of the process. A workflow engine is extremely helpful for orchestration because it allows you to model the flow explicitly and monitor it as it runs in real time.
Choreography and orchestration are both valuable communication styles, and different scenarios will call for one or the other. Effective architectures incorporate both styles and apply them where they best suit the communication need. As you design and implement microservices, carefully consider whether events or commands are the right approach for every single communication link between services.
Manage State for Long-Running Processes
In addition to communication management, state management is important for microservices. A business process that can’t be completed right away requires the state of process instances to be persisted until the process is finished.
In the order fulfillment example, receiving payment for an order is potentially a long-running process. A payment that is processed through PayPal might take a few seconds, while payments via bank transfers could take days or even weeks. The order fulfillment process has to wait for the payment to complete, which means that the state of every order in the system must be persisted.
The need to persist state data usually leads to additional business requirements. For example, if a payment fails, you might give the customer seven days to try a different payment method, which requires the system to track time and timeouts.
Figure 2: Timeout for payment in an order fulfillment process
A workflow engine is an ideal tool for managing the state of long-running processes. Most workflow engines execute process models that are expressed in a process modeling language. A prominent example is the ISO standard Business Process Model and Notation (BPMN), which allows you to design processes that are both graphical and executable. The workflow engine persists all data for instances of processes, even over long periods of time. It also facilitates monitoring, alerting, and reporting on a process level, often leveraging the visual as shown in Figure 3 (which indicates the number of active process instances for each task).
Figure 3: Order fulfillment process expressed in BPMN
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}