An App Service’s deployment slots are what you need to support testing/staging in your deployment process. And they’re also a way for you to test the “next” version of your application with real users.
At some point, you’re going to want to deploy your applications to an App Service that has a more robust service plan than the one you’ve been using for development (i.e., more CPU/memory, the ability to scale out or up, etc.). You could, of course, just upgrade the App Service you’ve been using to develop your application to a more powerful (and expensive) service plan. The reality, however, is that you’ll probably create a new App Service to handle the demands you expect in production. As a result, you’ll need to deploy your application to that new App Service.
For that new service, you will probably select one of the Premium service plans to provide that additional processing power that your production app requires. You can still select one of the original Standard plans but, since they’re now marked as “legacy,” they probably don’t have a future. Alternatively, you could create an App Service Environment (ASE) if your application requires the additional processing power ASEs provide or virtual network integration.
From the point of view of managing deployment (the point of this post, after all), the real benefit of picking one of those plans is that you can use deployment slots. Deployment slots not only provide a staging/testing platform for your deployment process but also provide a way to make the “next” version of your app available to some of its real users (including doing A/B testing with those users).
On that basis, I’m going to assume that you’ve created your production App Service, either by creating a new, empty service or by using the Clone app option on your App Service’s left-hand menu to create a new App Service with your application already loaded into it. To add a deployment slot to your new App Service:
https://warehousemgmtfrontend-test.azurewebsites.net
.In fact, after you click the Add button and your deployment slot is created, you’ll find that your App Service’s Deployment slot panel now lists two slots. That’s because, in addition to the slot you just created, your “original” App Service has become your “production” deployment slot (it’s even marked with a big green “Production” label—you can’t miss it).
You’ll continue to manage your production slot from your App Service page. To manage your deployment slot, surf to your App Service’s Deployment slots list and click on your new “testing/staging” slot. That will take you to a page where you can manage your new slot and, to some extent, separately from your production slot.
Your “production” slot is still accessed from the original URL you assigned to your App Service and still holds your application. Any existing clients will continue to be directed to whatever application is loaded into your App Service (of course, if you’ve just created the App Service, there won’t yet be any clients accessing your new service).
Typically, you’ll deploy the “next” version of your application into your “testing/staging” slot and use its URL to test your application in its new App Service (that’s in the next section—hang tough). Eventually, you’ll copy your application into your production slot and let real users access your application through the production slot’s URL (also coming up).
Over time, as your application evolves, you’ll deploy the “next” version of your application into your “testing/staging” slot, perform any final tests using the “testing/staging” slot’s URL, and (if all goes well) copy the “next” version of your application into the “production” slot. And so on until the application is retired or you move on.
You can, however, on the Deployment slots list that shows both slots, specify that some percentage of requests going to the App Service’s “production” slot are to be redirected to your “testing/staging” deployment slot. This is one of the major benefits of creating a deployment slot: By directing a percentage of requests to your “deployment slot,” you’ve enabled A/B testing for the “next” version of your application loaded into that slot. Any device that is directed to the version of your application in that deployment slot will have any subsequent requests also sent to that deployment slot.
As a result, you may want to set up additional deployment slots just for A/B testing rather than use your “testing/staging” deployment slot for that purpose. Alternatively, you may need to set up additional deployment slots because you have a release process that requires more than one “pre-deployment” slot. For this post, however, I’m going to assume the simplest configuration: a “production” slot and a “testing/staging" slot.
The relationship between the App Service, its “production” slot and any other deployment slots you add is … interesting. Critically, stopping the App Service only stops the “production” slot—any other deployment slots are only stopped if you navigate to them and stop them explicitly.
Creating a deployment isn’t like cloning an App Service—that option copies the whole App Service (including the application loaded into the service). Even if, when you create a deployment slot, you use the “cloning” option described further on, your new deployment slot is configured differently from your App Service.
When you create a slot, for example, while some configuration items are automatically copied to the new slot, others are not. If, when you create a slot, you choose the clone setting option while some additional configuration items are copied over (environment variables, for example), many configuration options still remain uncopied.
Your new deployment slot won’t, for example, have any identities (either system-assigned or user-assigned) assigned to it, regardless of what was assigned in the original app. As a result, any resource that restricts access by identity is going to reject requests from any application loaded into your new deployment slot.
While identities are not copied over, management roles are copied to the deployment slot: Anyone who had access to manage your original App Service has the same permissions for your new deployment slot. However, once you’ve created a deployment slot, you can assign different roles to different users to that slot (i.e., the people with management permissions for the “testing/staging” slot can be different than the people for your “production” slot).
In addition, there are some configuration items that can be set at the deployment slot level but are actually managed at the App Service level. Changing the service plan at the deployment slot level, for example, changes the plan for the App Service, not the slot.
And some items can’t be changed at any level. Virtual IP addresses and outbound IP addresses are tied to the App Service, not to the individual slots. That means if you’ve restricted access to some resource by requiring all requests to come from one of the outbound IP addresses of your original App Service, requests from the application loaded into your new deployment slot will also be accepted.
Therefore, purely as a matter of self-defense, once you’ve created a deployment slot, you should treat that slot as a new App Service that needs to be configured and managed on its own. Go through all the configuration settings thoroughly to verify your deployment slot is configured the way you want.
With your “testing/staging” deployment slot created and configured, you can now deploy your application to that slot either for A/B testing or for final testing/staging before moving the application to your “production” slot. Since you’ve been deploying your application to your development App Service, you already know how to deploy to your deployment slot—you just need to pick a different target.
In Visual Studio, the smart thing to do is probably to set up a new publish profile. As you work through the wizard, when you get to the “Select existing or create a new Azure App Service” page, you’ll need to drill down through the App Service you’ve selected to its Deployment Slots node and expand that to see your non-production slots. (In my case, that’s the slot I called “test.”) Picking just the App Service still works but it deploys to your “production” slot.
In Visual Studio Code, when you deploy your application, in the Azure pane, you’ll need to drill down through the correct subscription, through the App Services node, and find your App Service’s node. Once you’ve found it, expand it and, under the Deployment slots node, select your “testing/staging” slot. Once you’ve found the slot, you can right-click on it and select Deploy to slot as before.
When you’re ready to make the application in your “testing/staging” slot available as the production version of your app, start by returning to your App Service’s deployment slots list. Once you’ve opened that panel, in the menu across the top of the panel, click the Swap button to open a panel on the right showing your Source slot (by default, your non-production slot) and your Target slot (your current “production” slot). If you have more than two deployment slots, make sure that you’ve got the right slots selected before clicking the Start Swap button at the bottom of the panel.
When you click the swap button, in its simplest mode:
Any requests in process in the application at the time of the slot run to completion in the old version of the application, but any new requests are processed by the new version of your application (i.e., the old version of your application is “drained”). Under the hood, there’s probably less moving going on than that model suggests—some of the “swap” is probably just handled by redirecting requests from one version of the application to the other, but it sure looks like the two are exchanged.
After the swap, the swap button remains active. Clicking the button again will swap the two versions of the application a second time, leaving you back where you started (ignoring any activity performed before you swap back). Ideally, this means that if things go horribly wrong, you can restore to your original production system just by doing another swap.
Of course, you can make deploying to your “production” slot more complicated. Actually, you’ll probably have to, at least when it comes to managing your application’s environment variables.
It’s entirely possible (even, likely) that some of the environment variables on your “production” slot are different from the settings you have on your “testing/staging” slot. As part of clicking the swap button, you’ll want some of the settings on your “testing/staging” slot follow the application to your new “production” slot, which is the default behavior. However, there will be some environment variables you won’t want to follow deployment to the “production” slot.
For example, you may have an environment variable on your “testing/staging” slot that points to your test database and an identically named environment variable on your “production” slot that points to your production database. When you do the swap, you want that environment variable to stay with the “testing/staging” slot and for the new version of your application to pick up the value of your environment variable on your “production” slot. Similarly, you want the old version of the application (now in the “testing/staging” slot) to use the “testing/staging” version of the variable—if, for any reason, you do want to run the old version of the application from the “testing/staging” slot, you probably don’t want it updating your production database.
Alternatively, you may have another environment variable that you do want to follow the new version of the application into the “production” slot. The new version of your application may use a different log file than the old version of the application (you’ve done this to keep the two logs separate). To support that, you have identically named environment variables in both slots but with different values for the log file’s name. When you swap, you want the value of the log file’s environment variable to follow the new version the application to the “production” slot. Similarly, when the old version of the application is moved into the “testing/staging” slot, you want the value of its log file’s environment variable to follow it.
To distinguish between these two kinds of environment variables, you first, of course, need to set the value you want on each of the deployment slots for each environment variable. For any variable that you don’t want to follow its application to its new slot, you need to also check the Deployment slot setting checkbox on the panel you use for changing the environment variable. Checking this option pins that environment variable to that slot and the value of the variable will not follow the application to the new slot.
You want to check this option for the environment variable with the database reference, for example, so that whatever version of your application is in the “testing/staging” slot is accessing the test database (and whatever version is in the “production” slot is accessing the production database). You wouldn’t want to check this for the log file variable because you want the new version of your application to use its log file, no matter what slot it’s running in.
You’ll get some visual feedback on what values will follow the application to its new slot when you click the swap button. The panel that shows the source and target slots for the swap also shows any environment variables from the “testing/staging” slot that are going to follow the application to the “production” slot and overwrite the setting in that slot. My log file example would show up in this list because I do want the new version of my application to use its own log file (and my database setting would not because it’s pinned to the “testing/staging” slot).
When you click the swap button, the panel that appears also has a Perform swap with preview checkbox. If you check that box, the caption on the button at the bottom of the panel changes from Start Swap to just Swap.
Now, when you click that Swap button on the panel, the swap copies the deployment slot variables to your “testing/staging” slot. (It also updates the caption on the panel’s swap button to Complete swap.) To put it another way: The new version of the application, currently still sitting in your “testing/staging” slot, is now using the variables it will get when it moves to the “production” slot, including those variables normally pinned to the “production” slot.
You can now use the URL for your “testing/staging” slot to try out the new version of your application with the “production” slot variables. Using my previous examples, I’d be able to try out my new application with the production database (a deployment slot variable that, as part of a preview, is copied to the “testing/staging” slot) and its log file (a non-deployment slot variable that, as part of a preview, will still have the value to be copied to the “production” slot). Clients using the “production” slot’s URL, continue to use the old version of the application with its environment variables.
Before starting that testing, though, this would be a good time to review the environment variables on your “testing/staging” slot. You can now check that the combination of environment variables you want when the application is moved to the “production” slot are the ones currently on your “testing/staging” slot.
After testing the application using the “testing/staging” slot’s URL (and assuming that all that testing goes well), you can return to this panel and click the Complete Swap button at the bottom of the panel. The swap moves the two applications with their non-deployment slot variables to their new slots and restores the non-deployment slot variables in the “testing/staging” slot to their original values. Everything is as it would be after a normal slot.
If testing doesn’t go well, you still return to the swap panel to cancel completing the swap. Just above the “Complete Swap” in the panel button is a dropdown list displaying Complete Swap. Change that dropdown list to Cancel Swap and click the button at the bottom of the page (its caption will have been changed to Cancel Swap). The two applications stay in the slots they’re currently in and the non-deployment slot variables in the “testing/staging” slot that are restored to their original values. Everything is as it was before you clicked the swap menu choice.
As always, there’s more to talk about around deployment than I’ve covered here. You may, for example, want to set up CI/CD processes that target your “testing/staging” slot (and even automatically perform a swap). In your App Service’s Deployment Center (under the Deployment option in your App Service’s left-hand menu), you can connect your App Service to a source code repository (e.g., GitHub) and review any logs generated by any CI/CD process you set up.
You’ll also want to coordinate deploying your applications with deploying the other resources that your application requires (that production database that I referenced, for example), using ARM or BICEP templates.
This post, however, marks the end of the Coding Azure series. Hopefully, you’ll find one or more of these posts useful in walking you through creating secure, three-tier, cloud-native apps. Writing these has been a labor of love for me … which tells you a lot about my life, really. However, that also means that I doubt you’ll have as much fun using these posts as I’ve had writing them. That being the case, I’ll take the opportunity to thank you for your time, patience and attention through this very long journey.
Peter Vogel is both the author of the Coding Azure series and the instructor for Coding Azure in the Classroom. Peter’s company provides full-stack development from UX design through object modeling to database design. Peter holds multiple certifications in Azure administration, architecture, development and security and is a Microsoft Certified Trainer.