Microservices
Overview
Microservices are small independent and loosely coupled services that can work together. Each microservice is a separate codebase which can belong to individual teams, the internal implementation doesn't matter to other teams, only the fact that they communicate via an agreed or published well defined API, as such each service is technology agnostic, consumers do not care what or how the service was written or in what technology.
By following this structure microservices can be deployed independently and autonomously so can be updated in isolation and without affecting any other parts of a solution.
Ideally, if relevant, microservices have their own database or persistence layer which is not shared with other services, they are completely self-contained
Microservices architecture
Microservice architecture style is an approach to developing a single application as a suite of small services, each running in their own process and communicating with lightweight mechanisms such as HTTP or gRPC API or message brokers. Essentially the application is decomposed into small independent services communicating over well-defined APIs.
The services are loosely coupled, independently deployable by automated processes, organised by business capability ant bounded contexts.
Microservices provide a unit of software that is independently upgradeable and replaceable, organised around business capabilities, since only part of an application is affected updates are easier to deploy and roll-back if something goes wrong. Individual services are easier to develop and test and the smaller code base and dedicated data stores minimises dependencies making new features simpler and easier to develop.
Microservices can be scaled independently as the services should require fewer resources than a monolithic application, and only the required services need to be scaled out. Tools such as Kubernetes can help with this.
Obviously there are downsides to moving to microservices, not least of all an increase in management complexity. Whilst each service is simpler, the communication between them and associated deployments can make things very complex as the number of services increases.
Communication can also fall down if there are network issues or delays, the inter-service communication can become very chatty. Asynchronous communication patterns like message broker systems can help with this, but adds more complexity.
Integration and end to end testing also becomes more complex than monolithic applications.
The individual databases used by each microservice can also give rise to data integrity issues. Transactional operations are challenging, we should try to follow "eventual consistency" wherever possible.
Microservices should only be used when there is an advantage over implementing a monolithic application, things like agility in time to market, the need for zero down time deployments, and updates that need flexibility.
For existing codebases especially, a monolithic approach should be the default, but iterating and refactoring to possibly turn single modules into microservices one by one and see how it works out.
Backing Services for Cloud-Native Microservices
Backing services for cloud-native microservices are external components that microservices depend on for their operation which can provide support for things like data storage, messaging, caching, authentication, etc. They are treated as attached resources remaining external to the microservice. As such backing services can be swapped or replaced without changing the core logic of the microservice. By being decoupled from the microservice it promotes flexibility, scalability and easier maintenance.