We often hear that microservices should be loosely or de-coupled. The former reminds many software engineers of what SOA already stood for. Thus, there’s a common misunderstanding that having SOA is having a microservices architecture. However, there’s quite a difference, especially if you don’t look at the academic theories, but work on real-life projects that use these architecture patterns.
SOA and the Problem of Coordination
An application in SOA is split up into several components that can be developed independently. As these components have defined interfaces and communicate over a service bus, we call them loosely coupled. In theory a change in one component does not involve a change in any other part of the system. However, this is only true in very few cases, where components are only refactored or changes remain rather under the surface. In most cases the development and change of a component needs to be coordinated with others to fit in the overall design of the application.
Further, the commonly used ESB (enterprise service bus) style messaging between SOA services is not to be confused with the lightweight message queues between microservices. ESBs usually pack a lot of business logic inside them - changing components often means having to adapt that logic as well as other components that depend on the changed component.
On top of that, data in SOA is usually centralized, which means that data-related changes to components mean adjustment of the central data model, which in turn affect other components that work on that data.
I encountered these problems first hand in a security project, where we were building an integrated platform for supply chains. With 5-10 (the scope of the integration project increased over time) distributed, independent development teams, each working on one or more components that were all integrated over an ESB that held business process logic as well as a central relational database, the coordination task was never trivial. Over time, weekly coordination calls expanded from 30-60 minutes to 2-3 hours, resulting in fights between development teams and significant delays in delivery of components, and this was not even a huge project. Suffice it to say, the development teams as well as the business side were not very happy and compromises had to be made on the final featureset.
Microservices Architectures to the Rescue
Compared to SOA, in a microservices architecture we split up an application into simple, focussed services that are built around business capabilities. These services are highly decoupled and connect to each other over lightweight language agnostic communication mechanisms, which often times means simple HTTP APIs and message queues. Services are independently changeable and deployable with only a bare minimum of centralized management. They are polyglot in terms of programming languages, frameworks, and data stores used. Lastly, microservices are resilient, which means they are immutable artifacts that are designed to fail and are elastic in scale.
The message queues in microservices architectures are rather dumb pipes, where messages get sent and received asynchronously, while the message queue itself doesn’t hold any information on the application logic itself.
Further, data storage is usually decentralized and handled by each microservice by itself. Thus, each service can decide, which data store it wants to use and how. The data itself is abstracted away by the service using it only internally.
Because of these measures to decouple the services from each other, there’s very little coordination needed - it’s not loose coupling that but actual decoupling, which enables teams to focus on their own services and deploy them whenever they want instead of having to wait for other teams to adapt their services to the changes. Suddenly we can have continuous delivery of new or changed services with none or only very little coordination between teams. This in turn enables a continuous innovation process, where the company can quickly adapt to dynamic changes in the market and iterate on their product continuously.
Summarizing, we could say that microservices architectures are finally delivering on the original promises of SOA to have composition and independence in software engineering. However, they do it without the complexity and superstructure of real-life SOA projects. Sure not everything is rainbows right now and there’s many question marks as to how to move a monolith or SOA application to microservices or even how to split up the parts of a new system, but we’re still in the early years of this promising pattern and early adopters like Netflix and Amazon show that it’s very much possible to build complex systems with it.