Thinking about a deployment strategy for a microservices-based system it's natural to consider a rollback. Before looking for a technical solution, let's discuss this idea conceptually. Is it even possible to roll microservices back?
One of a plenty definitions of a microservice is an independently deployable component. This says actually a pretty lot. To understand this definition we have go back to the very first motivation for the microservices design pattern: We want to deliver our product as soon as possible. A microservice could be in hands of one team and have a completely different and unsynchronous delivery process. A team developing a service A don't want to be bothered by waiting for a next release of a service B if it doen't need its new functionality. The service A could be deployed into the production once a day and the service B once a month.
For all this to be possible we have to follow a few basic principles, especially the most important one in our context: No Breaking Changes. We may find the same principle under different names like "APIs are forever" etc., but the idea is the same.
No Breaking Changes
How does this principle makes the microservices deployment independent? Let's consider two services, A and B. B is calling A via A's API. In the time of development of a version v1 of the service B, there is a released API of the service A in the version v1. So the service B v1 makes its call against the service A v1:
During the development of the service B v1 a new version of the service A - v2 - was released. An additional endpoint was added, but it's okay for the service B because A's API was not broken (in other words, A v2 is compatible with A v1). Actually, so far there are no breaking changes the service B doesn't care which newly realeased version of the service A is talking to:
What about Rollbacks?
Now consider that the service B in some future version (let's say v2) is using an endpoint of the service A added in its release v2:
After some time the developers of the service A find an error in the v2. They decide to rollback to the previous version (v1). What happens to the system? The service B stops working because it keeps calling the endpoint of the service A v2 which doesn't exist anymore. The rollback to a previous version is a potential breaking change:
Because it can introduce a breaking change as the rest of the system depends on the current API a rollback should be avoided in microservices-based systems.
As long as we can't rollback microservices, we have to find a confident way how to deploy them into the production. There are a lot good practises like separated deployment stages (development, testing, QA, ...), testing in a production-like environment, blue-green and canary deployment, and so on.
It's also very important to resist the temptation of hotfixing a bug directly in the production environment. We alywas have to adapt the continuous-delivery principles: Every change, bug-fixes included, must be properly built and tested thru the standard deployment process (delivery pipeline).
Microservices are living organisms and should be treated like that.