Over the last couple years, companies like Uber, Amazon, Netflix, and Twitter have publicly declared that they have chosen to adopt microservices application architectures and have detailed their decisions to refactor existing applications in order to implement this approach. For these companies, rewriting their core business applications was no small task and required broad collaboration and orchestration of their entire engineering organizations in a shared effort. In the end, they all concluded that having a microservices application architecture would be worth the trouble. So what is so appealing about microservices and why should more IT organizations take note?
Simply put, event-driven microservices applications are characterized by a series of small, functional processes that run continuously and independently of one another and that communicate with each other via an event-based message passing framework. In an application, each pair of microservices that communicate with each other can cooperate without information about the implementation of the other service — all that is required is that they have well-defined APIs that they support respectively. In addition, each microservice runs in isolation and asynchronous of all the other microservices.
The overall logic of a microservices application, therefore, can be represented by a directed graph, like a flow chart, in which each node represents a microservice and a directed edge represents a stream of messages that are published by one microservice and consumed by another. In other words, a large monolithic application that encodes complex logic could be refactored into a microservices application by decomposing the monolith into discrete functional units and then connecting them via message streams in a topology that resembles the control flow graph of the original monolithic application.
In many ways, the principles of a microservices application design are the fundamental principles that are taught in every introductory programming class. Instead of writing a monolithic application, a microservices implementation exhibits abstraction (each microservice implements an API, but the implementation does not affect other microservices) and modularization (the program is broken down into small and independent logical components), and promotes reusability (each microservice can be reused multiple times in the same application or across multiple applications). This makes the program easier to reason about.