At the time being, Enterprise Architecture and patterns related to it, have evolved into a very solid set of principles. It is pretty straightforward to recognize patterns of enterprise architecture in fewer time than ever due to the knowledge we’ve been accumulating the last decade or so. If it has a peak, quacks and I can spot feathers it might be a duck after all.
Microservices are the natural evolution of SOA (Service Oriented Architecture). SOA is probably the most infamous and ambiguous denomination in terms of what exactly is. It was a very good attempt of breaking down old monolithic systems into something more manageable, but as usually happens, it was co-opted by vendors considering every single framework, tool or application a modern piece of SOA.
The biggest problem in SOA was the lack of boundaries and definitions in terms of what a service should be. Instead of a three (or more) layered system, many enterprise applications ended up in several services without clear boundaries and a lot of dependencies. A very common case was having a shared library that every single service knew, which pretty much tied all the system to a single piece of code that could break the entire application. Another common issue is the service did too many things, leading to a smaller layer but still pretty big and hard to maintain.
I don’t want to go further describing the issues founds on SOA during my career, but I want to say it started with good intentions, the result was not so great.
Microservices to the rescue
As I mentioned before, microservices are a natural evolution to SOA. At the beginning it was fairly simple to split off layered systems (classic view, business logic, database access systems) into services. Once systems grew larger and larger the SOA pattern became a nightmare, pretty big services with a lot of functionality and most of the time, heavy dependencies on each other. I remember to see in a company I worked for a Catalog Service (part of evolution to SOA) which was built 8-10 years before I joined and it required an entire server that kept growing in memory and CPUs. Simply, the catalog service did everything about the company’s products to the point it was an entire system itself, built into one particular service.
Also, systems are larger than ever. When I started working in software more than 25 years ago it was possibly for most developers to write any entire application from scratch. Five years later it was pretty much normal to have teams or 3-4 people. By the time I worked for a decade it was very normal that Enterprise Applications required dedicated teams of 10-20 people. Nowadays the amount of functionality, size of applications, data volume and complexity has sky-rocketed and it is very normal to have a code base that requires several teams.
In that context, microservices came to the world to solve those issues
What is a microservice?
I found many definitions of a microservice but I prefer to stick to the simplest one. They are small (important!), autonomous (more important!) services that work together. And the second question is, how small? Another simple definition I found is:
“So small that can be rewritten in most languages in less or around than 2 weeks”
The principle of a microservice is to do one thing well. One and only one responsibility. Hence, it sticks to the Single Responsibility Principle.
That definition can solve ambiguity at the time of designing:
“My service can manage catalogs and products”. That is incorrect, too many responsibilities, and if you have a very large company that manages tons of products, a “products service” simply won’t work, it will have too many responsibilities.
The autonomous definition is the key. Boundaries must be very clear and well defined. Microservices can change and be deployed independently, communication between services is enforced to happen via network calls. This definition makes the next step natural, services must expose an API.
An application programming interface (API) is core to microservices. To be fair, APIs have existed for decades in different forms such as RPC (remote procedure calls), SOAP interfaces, Java beans, custom tailored communications and so forth. It is common to think on an API as a RESTful API but it is not entirely true. APIs nowadays are mostly always REST APIs (I deliberately eliminated “ful” due to the fact many of them are not).
A microservice must expose an API which constitute the contract with that service. Every single communication with the service must stick to the API. For that reason, a microservice is not even tied to a framework, programming language or specific implementation. If I can expose an API the service can be coded in any possible way.
As a general rule it is fairly common to use HTTP APIs, they are broadly used and most languages have a lot of support to build them fast. They also have a lot of support to scale, if the microservice is well designed and implemented over HTTP calls, it is very simple to split the workload adding a load balancer on top of it and replicating the service in different machines (in this case machine is a blurry concept nowadays!)
What about queues?
Going back to the title you can tell I mentioned queues and you could be asking now why I mentioned it.
There is a common confusion about microservices architecture, queue based systems and using queues in microservices.
Microservices in many large systems tend to have heavy workloads. A normal approach to cope with it is using queues to defer execution. Let’s imagine a microservice receives orders to be delivered in a very popular e-commerce site, the service needs to keep up with requests at fast pace, it might be good to defer execution placing a payload in a queue to be executed as soon as possible, but the service itself it is not immediately executing it.
The confusion I mentioned is some microservices design tend to use the queue as a communication backbone instead of an API. Even when this is not entirely incorrect, it is pretty dangerous to use queues as the communication backbone. The reason is that placing a message in a queue transfers the contract to another system and there is no any restriction for any other service to consume that message. Boundaries get blurry.
To make it worse, not all queue software works in the same way. We might need to rely on a particular vendor that implements what we need to fit our design, coupling a loosely couple design to a particular vendor.
Part of the confusion is related to a different pattern. There is a reason to rely entirely on queues, when systems are designed as QBS (Queue Based Systems). Queue based systems are very particular, every single service consumes a payload that acts as a Unit of Work, external interfaces are not required (the service doesn’t need to expose an API). They share similarities with microservices but those services cannot be considered such.
Microservices Architecture is subject of entire literature about it, however, some principles are simple and easy to follow. The goal of this article is clarifying some design rules and warn about pitfalls and common mistakes. I will dig into those design principles in subsequent articles.