Dont think that moving to microservices will solve all your problems:
Moving to microservices can be ugly... if you dont know what you are in for. Microservices still requires good design just like a monolith does, so if a team is struggling with design on a monolith, they will probably have the same (if not more) struggles with microservices.
Spaghetti monolith - Coupling
We have all experienced a messy spaghetti monolith which was impossible to find anything or to make any simple changes... dont think microservices solves that problem outright. In fact microservices can make that worse. The same poor design from a monolith can be applied to microservices, except microservices will be worse because now you have the added problem of poor system visibility and not being able to detect the exceptions at compile time. Meaning with poor design, microservices are even harder to figure out than a monolith. Once you have figured out what changes to make on a monolith you can be confident in them due to there being less moving parts, compile time checks and easy testing.
"Bad programmers worry about the code. Good programmers worry about data structures and their relationships."
Many design principles used for a monolith still apply to microservices. For example defining the boundaries of classes/modules/layers is important for a monolith but is critical for microservices. Each service has a boundary which it exposes to the outside world, similar to an interface (except now it is via some protocol). Meaning a service often expects a specfic data model/structure. If these data structures are designed poorly and everything is using them, making changes can be a nightmare. ie services are coupled through the data structures. Changing such highly coupled models in a monolith is childs play compared to changing them in microservices. Often microservices have dependencies on other applications and if not designed well, a crash in one application can cascade across the entire system. ie Everything is highly coupled, the same way you may have highly coupled a monolith.
Defining is boundries is a topic on its own which we will cover later.
Vendor lock in
Vendor locking is less of an issue with microservices, because it is easy to simply rewrite a single services one at a time and eliminate a specific technology over time. Although this becomes difficult to do regarding communication between applications eg Akka, rabbitMq, Kafka, Rest. For example, if all your applications communicate via TCP using the actor model with Akka, it can be exceedingly difficult to change to HTTP, "locking" you into the use of Akka. Although it is possible to change, it is not always as easy as you would think, considering the hype around the decoupling of microservices.
Microservices comes with a whole range of great benefits but the pitfalls can be harsh if one is not prepared for them. All questions regarding the internals of each service can be left to the last minute (eg there is no reason to be specific on the language used) but some questions are best to be asked early. Spaghetti code, Coupling, Boundaries and Vendor lock are all design issues which are important to consider when designing microservices. The idea of just winging it because you are using microservices is absurd. Strong design still plays a huge role (see Agile Vs Design). The problem is that poor design will only affect the system down the line and is therefore often neglected in the early stages of development.
Here are some questions, concepts and technologies to look into before you consider microservices.
- How to communicate between services/clients? HTTP(eg Rest), Streams(eg Kafka), Queues(eg RabbitMq), WebSocket(eg SignalR), TCP(eg Akka)
- How to handle distributed data? CAP theorem, Streams, Queues, Event Sourcing, Schema Registry, CQRS, eventual consistency
- How to handle exceptions and down time? Circuit breakers, Actor model, Idempotency, Sagas, Distributed transactions, Queues
- How to monitor services? Distributed tracing (eg zipkin), Centralizing logs(eg Datadog), dashboards
- How to deploy services, scale and manage dependencies? Docker, Kubernetes, cloud(azure/aws/google), Reverse proxy(eg wso2, apigee), Schema Registry, Load balancer
- How to manage the devs? Agile, Git, TDD
- How to test? unit testing, integration testing, component testing, contract testing, end-to-end testing