Every web application at some point of its life cycle has to be updated for some reason: it may be changes in business requirements, rebranding, bug fixes, adopting new versions of the libraries it depends on, etc.
If all our users are from the same time zone, it’s quite easy to identify a maintenance time window that would allow us to take the application offline, apply the required changes and bring the application back online without affecting the operation.
When our application has users across different time zones, though, to take that application offline may not be an option.
This is where we’ll be required to do a zero-downtime deployment.
The process to do a zero-downtime deployment for a web application in Azure can be summarized as follows:
When we create an App Service in Azure, we can specify different deployment slots. These deployment slots are isolated instances of our application, with their own configuration and unique URL.
Once we define at least one slot, the default slot is labeled as “Production”.
For more information please go to https://docs.microsoft.com/en-us/azure/app-service/deploy-staging-slots
The next step we need to do is to identify exactly which changes need to be applied to the production environment to successfully update the application.
Do we need to update the database schema? Do we need to change the location from which the application is reading a file?
Are there other changes in the external resources used by the application?
This is really important for a successful deployment. If all the changes related to external resources are new locations to read files from, as long as the schema of those files remains the same, there are no extra steps to do other than updating the configuration settings for the file paths.
However, if we need to update the database schema, we have to make sure that the currently deployed application code is fully compatible with the updated database schema.
Since the existing code should be able to use the database exactly the same way as before the schema updates, the following considerations must be taken depending on the change we need to apply:
Before deploying the new application code:
Before deploying the new application code:
After deploying the new application code:
Before deploying the new application code:
After deploying the new application code:
Azure DevOps provides us with the capability to swap slots in our release pipelines. This means we can have for example a slot named “Staging” and do a swap between “Staging” and “Production” slots from a task in Azure DevOps.
Doing a slot swap with “Production” as the target slot ensures that the “Production” slot doesn’t have downtime.
To do a slot swap in our release pipeline, we just need to add a task to the stage representing our production environment:
For more information on what exactly happens during a slot swap please go to https://docs.microsoft.com/en-us/azure/app-service/deploy-staging-slots#AboutConfiguration
There are two important things to consider when deploying through a slot swap:
After following the process described so far, the different deployment slots for our App Service will be displayed in the Azure Portal like this:
NAME | STATUS | APP SERVICE PLAN | TRAFFIC % |
SampleAppService PRODUCTION | Running | MyAppServicePlan | 100 |
SampleAppService-dev | Running | MyAppServicePlan | 0 |
SampleAppService-staging | Running | MyAppServicePlan | 0 |
It’s recommended for our release pipeline to have the different stages configured to be deployed only after the previous one is deployed successfully.
It’s also recommended to configure pre-deployment approvals on each stage, especially in Production. That would allow us to test the web application with the same settings as Production, so we can catch any errors that may be happening on that specific configuration before they affect the end-users.
If we have integration and/or end-to-end tests in our project, it’s also a good idea to have the release pipeline run them and only deploy to Production once all these tests pass.
The stages in our release pipeline would look like this:
Planning a zero-downtime deployment is no trivial task. Once we identify the need for a zero-downtime deployment, the planning should ideally start during the early development of the changes we want to include in that deployment. This is mainly because part of the steps mentioned above includes using new names for existing external dependencies (like stored procedures) and making several changes to our Azure environment and Azure DevOps release pipeline.