Microservice is a term that started to be really hot in 2014. Companies around the world and software engineers are paying since then special attention to this paradigm as a new way to think about structuring applications.
In short, microservices relates to a way to modularize big applications, so, each microservice is independent in the form and autonomous in the type of execution compared to the others. The inter-service communication is always using standards, like HTTP, and use to have the operational form of RESTful services or messaging buses:
- The REST paradigm is quite close to the microservice paradigm.
- The messaging buses are not ESB-like, where all application logic is on the bus, but more event oriented buses, where the microservice owns the business logic and uses events to warn other microservices actions should be taken.
The original microservice concept.
In their original whitepaper, the authors explain that "the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized managementof these services, which may be written in different programming languages and use different data storage technologies" (J. Lewis, M. Fowler).
But, what does all means really? It means this new paradigm, a philosophy of work, a group of technologies and a set of best practices, for instance being used since lately 2000, involves software that should be created to achieve several precepts by design alongside with their business objectives:
- Componentization via Services: No more libraries, no more bundles, no more packages. Each microservice is what its name represents, a service. Microservices does not relate to the size of the application inside but to the way they behave in group. Microservices have single responsibility, are loosely coupled and are highly cohesive. That means, each microservice serves for one concept or (business) objective. A highly cohesive component encapsulates one concept. Simply speaking, it does one thing well. Highly cohesive modules are easier to understand, easier to maintain, and easier to reuse. The idea of loose coupling relates to how tightly the behaviour of one component is bound to the implementation details of other components. As you will read later, the database is not anything else than an implementation detail and cannot drive the work of any microservice. Simple evolution is the final objective.
- Organized around Business Capabilities: This refers to the fact that each microservice is created to solve one single business objective. Teams working on microservices are multidisciplinary, so, e.g. tech guys, functional guys and business guys work together to provide the correct vision to what the business needs. In a tech jargon, teams working on microservices are typically "two pizza teams", a definition coming from Agile development and coined by Amazon, meaning that the teams are not bigger than 6 or 8 people working per microservice at the time.
- Products not Projects: This point is difficult to explain on a general way as it encompasses the company idiosyncrasy, people likes and dislikes and common behaviour per industry, but, in general it refers to the fact that the team that designs a microservices is the same team that builds it, the same team that evolve the service and that run operations. In this case, when a team needs to deal with a microservice they see the code as a complete product, rather than just a project we need to face temporarily.
- Smart endpoints and dumb pipes: In short, do not create ESB (Enterprise Service Bus) anymore. The business logic must reside in the microservice, not in a common line of communication. This creates bottlenecks and inefficiencies. The organization reflects what their software is (M. Conway's law).
- Decentralized Governance: There's no more architects that rules the software building process. Architects should look after standards usage and platform being operational, but should not force the development teams to use specifics like language or persistence models. A decentralized governance produce anti-fragility and this anti-fragility produces agility and speed.
- Decentralized Data Management: Each microservice has its own database, or even better, each microservice has its own implementation details. There's no more integration by database, this practice is from the past. There's no more canonical database model. No more database tables full of null fields per row. Databases are implementation details.
- Infrastructure Automation: Infrastructure as code. Automation is a must to be able to work with microservices. They are a lot, and operations are quite difficult if certain degree of automation is not in place.
- Design for failure: You must think microservices are made to fail, as like the technological ecosystem fails too, but, this fact is something that makes the microservice paradigm strong, as you already are aware of that and build infrastructures that are redundant, and follow best practices to get business continuity, thus you are resilient by design. Following this behaviour, you will never lose the 100% of your system, or you won't lose the full system functionalities, just only some of them. This is the cloud way of life.
- Evolutionary Design: You are not forced to build the definite service that will work forever. You can start writing code to solve that part of the business need you best known and slowly introduce changes in the microservice as you know better what you are facing. You don't need months to study a certain situation, you can act quickly and evolve with the microservice as the real need evolves. That's awesome, because you can start providing something useful for the business since moment zero.
The good, the bad.
Every decision comes with trade-offs. Microservices couldn't be less:
- PROS: Microservices reinforce modular structure, which is particularly important for larger teams. Simple services are easier to deploy, and since they are autonomous, are less likely to cause system failures when they go wrong. With microservices you can mix multiple languages, development frameworks and data-storage technologies.
- CONS: Distributed systems are harder to program, since remote calls are slow and are always at risk of failure. Maintaining strong consistency is extremely difficult for a distributed system, which means everyone has to manage eventual consistency. You need a mature operations team to manage lots of services, which are being redeployed regularly.
Revolve on the thing
A couple of simple yet repetitive in happening examples that illustrate common situations we all face while architecting a software solution:
- Several micro applications running alone but attacking a common database is not microservices. These could be more similar to a SOA architecture. Despite it can be useful, it is not microservices. In microservices each microservice has its own logic and the use of a database is an implementation detail only. The important is to provide and API style, a way to provide data, or request it, to/from other microservices. The way the information is stored should not be important. Moreover, microservices can be able to change data storage, and business logic, internally and without affecting other microservices.
- Microservices communicating among them not using REST is possible, but it will be much more difficult its broad integration into the microservice ecosystem. The use of HTTP is important to take advantage of everything already in place for the HTTP standard, like caches, load balancers, proxies, .... and the like.
“While our experiences so far are positive compared to monolithic applications, we're conscious of the fact that not enough time has passed for us to make a full judgement.”
-- James Lewis and Martin Fowler