A recent topic grabbing the stage in the software community is the use of Microservice Architectures. Microservice architectures are often sold as a great way to enhance a project’s agility over a standard, monolithic architecture. While this can certainly be the case, and there are indeed many benefits from using microservices, the use of a microservice architecture also brings about many unwritten challenges to the way software is designed, developed, and put into production. In this article, we will lay out some of the positive characteristics specific to using microservices that we’ve found while implementing them in a production setting.
First, if you haven’t heard about microservices, the basic tenet behind them is to break up what would normally be a single, “monolithic” application and instead build many small parts or services that run as completely separate processes. In the made-up example company intranet shown below, an application front-end speaks with the business logic for the shipping and accounting departments as well as management, who need a way to get analytics for all departments, including engineering. In the case of the monolith, each of the departments speak to a single, shared database with all information for all departments.
Consider the case that management asks to have real-time insight into the current financials based on inventory levels. As opposed to abiding by the accounting interface, the developers of the management business logic decide it’d be more effective to go straight to the database (because it’s faster, of course) in order to get the current numbers in the warehouse as well as the sales so far that day. This immediately couples Management, Accounting, and Shipping. While an extreme example, this sort of shortcut is typical in many monolithic applications in production today.
Compare this with the use of a microservice-based architecture. Each service has its own database containing only the information that is pertinent to the business logic of said service. In the previous example, the developers of the management business logic would have no way to get the information they need about the current warehouse inventory other than by asking the shipping API.
The use of microservices can provide many positive benefits to an application’s lifecycle. We get code separation, we can enforce an API at the service boundary, and software ought to be more agile as a whole because it’s made up of only small, independent parts. Unfortunately, as will be discussed in a follow-up article, these positives often come with some undesired surprises. For now, we’ll stick with the positive:
Small, continuous deployments. Due to its very nature of small, independent services, using microservices has made it easy for us to design, develop, and push small changes with little concern for what might break. Instead of changing a codebase of >>100,000 lines and having to wait for weeks or even months to deploy a single feature, a service of potentially less than a thousand lines can be changed and pushed up multiple times a day and (for some) put immediately into a production environment. This has led to really good flexibility with each service itself as well as the overall architecture.
Architecture flexibility. Building off of the previous point, the agility given to us through the deployment of small, completely independent microservices has provided a ton of flexibility in the architecture. As technology changes, new services can be added or dropped. New project demands can be satisfied without effecting work that has already been done in another service. Services can be built to leverage a new and cutting edge technology with much less risk. New languages can be explored without having to fully “dive in”. The flexibility is great, but we’ll leave the remainder of the possibilities up to your imagination. In summary, using this architecture provides a lot of options for technology as demands and trends change throughout the lifetime of an application.
Single service scalability. By having each service operable as an independent unit, when a certain function of our application receives higher demand, that service can be scaled behind a load-balancer on its own rather than having to start up multiple instances of the entire application like would be done with a monolith.
Code boundary separation. By literally breaking up the application into multiple applications, it is more difficult for us as developers to tightly couple code. The current suggestion by most (depending on specific implementation) is to use a protocol like REST for communication between services. While we often strive to program to an interface in a monolithic architecture, it becomes all too easy with a monolith to forego this because of its convenience. Using REST, however, it is much more difficult to do this.
There are plenty of positives that can be gleaned from using a microservice-based architecture. These are a select few we think have been the most prevalent and practically useful thus far in our work. Be sure to keep an eye out for our follow-up article that will discuss the other face of microservices: the challenges. There are also a ton of great resources out there already and will continue to be many more as the use of microservices continues to grow.