A particularly established trend to develop new applications is the use of microservices thanks to their flexibility and versatility.
But what are microservices?
Microservices are an architectural style that involves the creation of applications starting from the development of independent modular services - microservices, in fact - devoted to the performance of a specific function.
A microservice is an independent software element, which autonomously represents and performs a specific business function: for example, a CRUD microservice is dedicated to carrying out creating, reading, updating and deleting operations on a collection of data.
Again, we might call "payments" the microservice that carries out a commercial transaction; “catalog” is the microservices responsible for managing a product catalog; “prices” is used to calculate the price of a product; and so on.
All these microservices carry out together a business transaction, such as buying a product online.
History and distinctive features
This application development approach is not entirely new.
Originally, application development used to be organized following a monolithic approach: the app source code used to be executed in a single deployment unit.
The applications conceived and built as monoliths were easy to design but had a series of limitations: poor ability to evolve with new and heterogeneous technologies, complexity in guaranteeing business continuity, limited scalability and rather long release times. They were not suited to evolve over time to meet new business needs.
Thus the SOA (service-oriented architecture) architectural style emerged. It was based on the idea of exposing services and functionalities that are reusable and easily integrated with one or more applications through standard communication protocols (for example SOAP, HTTP or JSON / HTTP), and an Enterprise Service Bus (ESB). However, the use of an ESB can be a risky approach, since it implies the existence of a single point of failure for the entire system.
A first evolution in the direction of the microservice architectural style is the Hexagonal Architecture - or Port Adapter - born with the aim of creating decoupled application components, which can be easily connected to their software environment through ports and adapters.
The microservices architecture style is different from the other approaches for a single characteristic that affects the design phase: each service is conceived as an independent part of the architecture, with a single purpose (the execution of a function), well defined parameters, and that can be developed and released independently.
The services expose information and communicate with each other through programming interfaces (API), event streams or message brokers, which are independent of the language and thus guarantee a certain freedom and flexibility to the development team.
In addition, the emergence of containerization technologies, which allow different parts of an application to be run independently and on the same hardware, has facilitated the emergence of the practice of using containerized microservices at the basis of the development of cloud-native applications.
We have already talked about the independence of microservices as their fundamental and distinctive feature that affects all the life stages of each service - design, execution, testing, release and subsequent evolutions.
This feature is reflected in various areas, from the organization of teamwork, to the management of releases and potential malfunctions. For example, teams can work independently on the development of different features, without creating internal dependencies for the same API exposed and consumed.
As microservices are designed and developed as independent units that perform a single function and respond to a single business logic, can evolve or scale independently, according to the specific business needs.
You can scale each microservice horizontally or vertically, and you can avoid scaling the entire system, as is typical for monolithic applications.
Furthermore, since the services are independent of the underlying technologies, these too can evolve or change, avoiding lock-in and without impacting on the functioning of the services themselves and the end-user experience.
As we have anticipated, each microservice is responsible for carrying out a specific function. For this reason, defining the extent and limits of responsibility of each microservice is essential. It is an activity that must be performed in the design phase in order to have a balanced, flexible, fast, scalable and easily maintainable application.
A central role in defining the boundaries of each service is played by the single responsibility principle (SRP), introduced by Robert Cecil Martin: it prescribes that each microservice must be responsible for only one function. This principle can be considered the starting point in defining the limits of each microservice, but it can be useful to follow other indications such as the Domain Driven Design approach.
In general, to correctly define how large a microservice should be, you need to evaluate several points, which take into account the role, requirements, technology and isolation requirements of each service.
Decoupling and interoperability
Microservices typically expose functionality using a technology-independent, loosely-coupled integration mechanism (HTTP REST).
This allows you to use different technologies (and languages) within the same application (e.g. Java, .NET, Python etc) and to make them evolve over time without impacting the final result and user experience.
Furthermore, a RESTful API type communication offers advantages such as reduced bandwidth usage, great flexibility in the format of the data returned (XML, JSON, YAML etc.) and ease of integration with third-party systems.
Microservices favor the implementation of automated processes and practices.
For example, they easily integrate into Continuous Delivery and Continuous Integration practices, in which the goal is to automate processes as much as possible to have a reliable, repeatable and simple deployment pipeline.
In this way, by using tools for the integration and execution of the processes that lead to delivery, it is possible to manage hundreds of microservices from a single platform, with considerable savings in time and costs and better governance of the entire code lifecycle.
The benefits of developing with microservices
As we have seen, microservices have specific characteristics that distinguish them from other software development styles.
Building a microservices architecture means developing the various functions of which it is composed as independent modular services. This brings with it particular advantages, which involve both the more technical aspects and the business point of view.
Let's see them in detail.
Adaptability to business needs
The first advantage coming from independence and evolvability of microservices is the possibility to modify and adapt the software product with simplicity and speed, according to the business needs. As it is a combination of independent elements, which communicate with each other through a standard protocol and can scale as needed, it is possible to take action quickly on the individual features to modify, improve, evolve or even overturn the final product, to meet the ever-changing needs of the business. In this way it is possible to create an application architecture capable of evolving with the market.
In addition, by using APIs for exposing information to the outside, microservices ensure excellent integration with external services, applications and systems, offering the business the opportunity to develop new partnerships and commercial agreements with third parties.
Simplified management of the software product
Since microservices are independent, you can easily manage the software: in particular, the principles of SRP and bounded context, which guide the writing and evolution of the code, ensure that the evolution of the software is linear and simplified in every component.
In addition, the ability of teams to work independently and in parallel on individual features offers CIOs a simplified governance of the entire product evolution cycle.
Reliability and simplification of the development and release phases
The integration with CI/CD practices, as we have seen above, allows you to work with small and frequent releases, and to automate the development, testing and release of the code as much as possible. This guarantees not only greater ease of management and considerable time savings in the various phases leading to the release of the software, but also the creation of a repeatable - and therefore reliable - pipeline.
Furthermore, in a system fragmented into many independent entities, larger or smaller, fewer dependency problems will necessarily arise, and any rollback activities will be easier to manage, investing a limited and isolated part.
From a security point of view, it is advisable to invest time and pay particular attention to the issues of responsibility, communication and dependencies between microservices already in the design phase of the application. For example, a service that by its nature is exposed to particularly high workloads or potential external attacks, if properly isolated, will not risk becoming a point of failure for the entire application. In addition, the ability to isolate errors and malfunctions simplifies their management and improves the reliability and safety of the entire system.
Containerization and Kubernetes
If we talk about microservices we cannot fail to mention containers and Kubernetes, the most widespread and used container orchestration tool.
The practice of containerization makes it possible to put an application and all its dependencies in a single container, allowing the software to be distributed reliably.
Kubernetes is the ideal tool for orchestrating containers and building high-performance microservice architectures.
Working with microservices: the Feature Teams model
A good way to approach microservices development is to organize teams to reflect the development model - each feature is an independent and finite element - which in turn traces the structure of the final output.
This structure is called feature teams: cross-functional teams that work on single features vertically, operating end-to-end throughout the lifecycle of the functionality they implement.
In this way, combining skills of back-end and front-end development, UX / UI design, API design and maintenance, knowledge of business logic, testing, deployment, operations etc. the team will be able to independently manage its functions, with an overview of what the final result will be. The team is responsible for the microservices it develops, from start to finish.
Microservice development points of attention
Despite the numerous and considerable advantages, even this architectural style brings with it some critical issues.
- Testing an entire microservice application can be difficult. In particular, while testing a single microservice is a simple and rather profitable operation, testing the entire application requires a series of activities and greater attention.
- In distributed transactions it can be complex to ensure the consistency of data, which is updated in parallel by different microservices. In this context, Saga Pattern is an architectural pattern that is establishing itself as a successful practice.
- Debugging the entire application could take a long time, since each microservice has its own set of logs. Therefore, it may be necessary to review several logs before identifying the point where the error occurs.
From this point of view, it is even more important to always have control and visibility over all the services running, to monitor their health and promptly identify any points of error.
- Governance: In large enterprise environments, it is common to have hundreds or thousands of microservices in production, with different development teams, each working independently according to their habits. In this context, in order to have a clear governance of the entire microservices ecosystem, it is advisable to standardize processes and methods as much as possible. To support this goal there are various tools, such as Mia-Platform Console, which supports development teams and at the same time helps to oversee IT activities and govern the systems entirely.
- As complexity increases, the need for a valid and effective monitoring system grows. Among the recommended best practices we find, for example, the use of monitoring and orchestration tools for the containers in which the microservices are run; a good API security strategy that includes monitoring API calls affecting microservices; continuous visibility on the health of each service, so as to be able to intervene as needed.
- As we have seen, the microservices architectural style allows you to use the tools and languages you prefer. For this reason, keeping the documentation updated and understandable is fundamental: it cannot be considered an accessory tool, rather an indispensable step in the development cycle. This aspect is particularly important to facilitate integration with third parties.
Migrate your applications to microservices
This development model, in addition to approaching applications and digital projects from scratch, can also be used to modernize legacy systems anchored to a centralized architecture.
By developing specific microservices, it is possible to decouple systems from channels, gaining autonomy in the development and management: the underlying systems continue to work - relieved of potentially excessive workloads - but do not have a direct relationship with the channels.
The channels, free from the constraints of performance and system availability, make it possible to provide an integrated and flexible offer of high-performance products and services, which can be enriched, scaled and evolved freely.
Furthermore, by adopting an incremental approach, it is possible to progressively migrate the various functions towards a new lighter, more flexible and evolvable system.
Read the case study of a large insurance company that has been able to transform and improve the maintainability and governance of its IT systems with Mia-Platform.
Finally, if you want to go deeper into the topic of microservices, we've selected five books on microservices architectures that we think you shouldn't miss.