By now, we can safely say the hype surrounding microservices has died down and microservices are here to stay. When you read about microservices you might get the impression they are an “all or nothing” affair and you should rebuild your entire architecture using microservices. If this sounds daunting, rest assured, this isn’t the case.
Like I explained in an earlier blog, a microservice is, for all intents and purposes, just like any other service that adheres to the principles of service design. The main difference between them is the way they are implemented.
A regular, or traditional, or non-micro service is a service that exposes a piece of business-oriented functionality. In general, this functionality is provided by a larger system that exposes more of these services. Depending on the type of system they can expose technically oriented services (like CRUD operations) which in turn are used by the business service. Key here is that that multiple services share the same stack and backend system.
A microservice, on the other hand, is implemented autonomously. Not only functionally, but also at runtime. This means they operate in their own dedicated stack, all the way down to the datastore. Basically, they are small monoliths.
When I talk about the two types of services, I like to refer to them as castles (services on a shared backend) and towers (microservices), which is based on how I usually draw them:
The analogy mainly means that you want to have towers (business level services), however, they can either be independent (a microservice) or on top of a castle (a larger system).
The point I’m making here is that they don’t need to be exclusive. You can combine them. As long as they both expose business level services you can mix and match (but be careful not to introduce dependencies). One of the key benefits of working with services is that you don’t need to be concerned about how they are implemented. A system should completely cover a certain bounded context. It can even cover multiple contexts. But a bounded context should not cross over multiple implementations. The high cohesion guideline applies here.
This concept is especially true when buying software. COTS can be a great way to gain mature functionality fast, but a lot of organizations have then gone on to “get the most out of their investment” and extend those systems through customization. This not only creates issues with upgrades (and therefore diminishing one of the key advantages of COTS), it also blurs the bounded context of the system. When buying software, try to find something that fits a certain business capability (aka bounded buy) and then leave it be!
Microservices have their own benefits and challenges, thus when considering a microservice implementation, you need to be aware of the pros and cons. In general, the two key benefits are scalability and flexibility. If these aren’t concerns for your organization, think really hard about going with microservices.
The choices you make don’t need to be final. If the services are implemented properly, they should act as a decoupling mechanism between functionality and implementation. This means you should be able to replace them without impacting their consumers too much. Meaning you can take a legacy system of record and replace it with a set of microservices, or replace some microservices that don’t change as much as you thought with a SaaS solution. All with relative ease.
Microservices aren’t a silver bullet and don’t need to be implemented as such. A lot of their benefits come from following the principles of service orientation. You can experiment with them without throwing out everything you currently have. See what works, keep anything that does and lose everything that doesn’t.