Most of you are probably quite familiar with monoliths. It’s a common architectural pattern where an application and its tightly-coupled components are all part of a single code base and are deployed together. The big advantage of monoliths is that they’re simple to understand and build. There are plenty of developers who are familiar with building them, and so there’s likely no learning curve involved with building them, and the design and dev effort is minimal. Don’t forget, however, that even if you intend to use a monolithic approach you should still try to follow at least some of the cloud-native app principles.
On the down side, monoliths have some issues across the remaining considerations. Monoliths are relatively easy to deploy, but because your deployment replaces the entire monolith there can be significant risk if the deployment fails. However, it is still possible to do rolling deployments and even blue-green deployments.
Because all of a monolith’s components tend to be compiled into a single deployment artifact, and each component might incorporate changes or new features, a stereotypical monolithic deployment tends to bundle multiple changes or new features. The higher the number of changes/features being deployed, the higher the chance of a failed deployment, or of introducing bugs.
Finally, monoliths scale out linearly. That is, if you need to scale out to handle increased demand, you’ll need to stand up new instances of the entire monolith. Compared to microservice-based architectures, scaling a monolith is inefficient because it is common that the high demand only impacts a couple of components. As such it would be more efficient to scale only the impacted components.
Microservice-based architectures are frequently a preferred approach for app modernization efforts, and the advantages and disadvantages are nearly the opposite of those with monoliths. You’ll be facing a steeper learning curve with microservices, and since many organizations are moving from monoliths to microservices, you’ll need to figure out how to break apart your monolith. For a large monolith that can take some time. And after you’ve ripped apart your monolith you’ll have to figure out how to re-integrate the microservices to work together using the 12-factor principles (e.g. loosely coupled and resilient). Services can communicate using various approaches, such as RESTful calls or reading/writing to queues.
From a deployment perspective you’ll have more things to deploy, and likely more frequent deployments. However, in the microservices world, automation is your friend, and your deployments should be automated to minimize time & effort, as well as improve reliability. Also, while you’ll have more frequent deployments they should include fewer new/changed features, which minimizes risk. This is actually a huge advantage. Having fast, automated, and low-risk deployments of services leads to a much higher rate of deployment success, and therefore higher reliability overall.
With regard to hosting considerations, hosting microservices can be much more efficient, because you can scale the various microservices independently. For example, if service A is getting thrashed with requests, you can scale out by adding instances of that service to meet demand, and then scale in when the demand declines. Depending on your hosting configuration, you may be able to scale out those services on your existing compute resources, saving costs.
It’s worth mentioning that in the microservices world there are quite a few frameworks to choose from in that space (e.g. Spring Boot and Service Fabric). Or you can skip the frameworks and roll your own. But if you do choose to modernize your apps using a microservice-based approach, you should invest some time reviewing available frameworks.
There is a lot more to discuss regarding microservices, but we’ll keep it short and wrap it here.
Using containers for packaging and deploying apps is a great way to go. Using containers all but forces you into using many of the 12-factor app principles. However, it does not necessarily force you into completely modernizing your apps, or into using microservices. The container ecosystem supports both Linux and Windows deployments, but as of this writing, the Linux container ecosystem is much broader than the Windows container ecosystem. For example, at present Kubernetes only partially supports Windows containers.
Containers have some of the same advantages and disadvantages as microservice-based apps. They bring some significant complexity and an associated learning curve. But the deployment and Ops stories can be similar to microservices, and even better if deploying to and hosting within a container orchestrator like Kubernetes, or a Kubernetes service like Azure Kubernetes Service (AKS).