<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Anders Wahlqvist</title><link href="http://world.optimizely.com" /><updated>2021-12-10T10:43:49.0000000Z</updated><id>https://world.optimizely.com/blogs/anders-wahlqvist/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>EpiCloud 1.0.0 released!</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2021/12/epicloud-1-0-0-released/" /><id>&lt;p&gt;This week we have released an update to the PowerShell module used to perform deployments through &lt;a href=&quot;/link/cecd04dddeea47f89a14d7f163913728.aspx&quot;&gt;the deployment API&lt;/a&gt;, it&#39;s available through &lt;a href=&quot;https://www.powershellgallery.com/packages/EpiCloud/&quot;&gt;the PowerShell Gallery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No changes in this module should be breaking, but we have improved a couple of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The module is now officially cross-platform compatible&lt;/strong&gt;&lt;br /&gt;Are you using Linux to run your builds? No problem!&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clearer error message when uploading a code package with the same name twice&lt;/strong&gt;&lt;br /&gt;Overwriting an existing code package is not supported (for CMS 12/Commerce 14 and above) and the deployment API will throw an error when this is attempted. That error message has now been improved so it&#39;s clearer.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The module no longer requires Az.Storage or Azure.Storage PowerShell modules to run&lt;/strong&gt;&lt;br /&gt;The module is now completely standalone, making it easier to use on the various build runners that are available in Azure DevOps etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our hope is that this will make deploying changes to DXP even simpler than before!&lt;/p&gt;</id><updated>2021-12-10T10:43:49.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Introducing &quot;Direct Deploy&quot;, a quicker way to deploy to integration using the deployment API!</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2021/3/introducing-direct-deploy-a-quicker-way-to-deploy-to-dxp/" /><id>&lt;div&gt;
&lt;p&gt;Deployments in DXP are designed to be as seamless and non-disruptive as possible. We&#39;ve also added a few steps that might not always be associated with a deployment process (like automatically configure warmup, validating some configurations to make sure they&#39;re compliant with the service, migrate environments to the latest version of the service configuration etc.).&lt;/p&gt;
&lt;p&gt;Before the new code is live, you also have an option to validate the results before live traffic hits the new version (using slots). This can be very useful, but since &lt;a href=&quot;/link/ce80e6dd766c40aeaa9be6b4f5d88430.aspx&quot;&gt;warmup has to finish&lt;/a&gt; before the site can be swapped, it&#39;s also quite slow compared to a deployment where binaries are simply pushed to a web app.&lt;/p&gt;
&lt;p&gt;While this approach makes a lot of sense for production sites (&lt;a href=&quot;/link/cecd04dddeea47f89a14d7f163913728.aspx&quot;&gt;and is fully automatable with the deployment API&lt;/a&gt;), we&#39;ve received feedback that it would be nice to have a quicker option to deploy to DXP as well, especially to the integration environment. This has been possible for quite some time, but we felt it was a bit awkward to have to use a different method to deploy to Integration compared to the Preproduction/Production environments, especially if you&#39;re already using deployment packages.&lt;/p&gt;
&lt;p&gt;We&#39;ve therefor added a new option for deployments targeting Integration, &lt;em&gt;Direct Deploy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Direct Deploy can be triggered through the deployment API and &lt;a href=&quot;https://www.powershellgallery.com/packages/EpiCloud/&quot;&gt;the EpiCloud module&lt;/a&gt; (&lt;a href=&quot;/link/eb85a23d0c1843aaa36f121668e1059e.aspx#webapp&quot;&gt;using the -DirectDeploy switch for Start-EpiDeployment&lt;/a&gt;). This will trigger a deployment that doesn&#39;t utilize slots. It will still &lt;a href=&quot;/link/f8095ba67d6243d5960675015884e355.aspx#ConfigTransforms&quot;&gt;apply configuration transforms&lt;/a&gt; so you can use the same &lt;a href=&quot;/link/d960958cd9f0474782c58adb311032b1.aspx&quot;&gt;deployment package&lt;/a&gt; for all environments, but it will simply just push that package directly to the &quot;live-slot&quot; of the target environment (which will be disabled during the deployment, meaning the target environment will be offline for the duration of the deploy). It will send a request to the target site to trigger the warmup process, but it won&#39;t wait for it finish. Nor will it configure a warmup section automatically even if it doesn&#39;t exist.&lt;/p&gt;
&lt;p&gt;This makes it possible for us to complete the deployment for you much quicker than before, and we hope you&#39;ll find it useful when you simply just want to run the first few functional tests in the Integration environment, and therefor want the deployment to finish as quickly as possible.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/5580c098b8d847939c3ee3d128028eb5.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Finally, I would like to ask you to keep &lt;a href=&quot;https://feedback.episerver.com/&quot;&gt;providing us feedback&lt;/a&gt; on how we can improve, we really appreciate it!&lt;/p&gt;
&lt;/div&gt;</id><updated>2021-03-09T08:07:37.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>DXP deployment improvements</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2020/4/dxp-deployment-improvements/" /><id>&lt;p&gt;We&#39;ve been working on a few improvements related to DXP deployments lately and wanted to share some recent and upcoming updates with everyone, we really hope you&#39;ll enjoy these new features!&lt;/p&gt;
&lt;h2&gt;Deployment API updates&lt;/h2&gt;
&lt;p&gt;The deployment API has been very well received and we&#39;re therefor investing further into it&#39;s capabilities by enabling a few new features for the API first in time for it&#39;s GA release.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/2269517d4d8a4cd4a096080a7d24dbd5.aspx&quot; /&gt;The ones we released recently are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Content syncdown&lt;br /&gt;The API now supports triggering content syncdown (copying of DBs and/or blobs) from the Production environment to Preproduction/Integration. If you&#39;re using the &lt;a href=&quot;https://www.powershellgallery.com/packages/EpiCloud&quot;&gt;EpiCloud PowerShell module&lt;/a&gt;, you can use the&amp;nbsp;&lt;span&gt;&lt;strong&gt;Start-EpiDeployment&lt;/strong&gt; cmdlet with the &lt;strong&gt;IncludeDb&lt;/strong&gt; and &lt;strong&gt;IncludeBlob&lt;/strong&gt; parameters to start a content syncdown.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;DB export (bacpac)&lt;br /&gt;&lt;/span&gt;&lt;span&gt;This is a completely new endpoint in the API that supports exporting a database to a downloadable bacpac file that can be used for local development purposes for example. The&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.powershellgallery.com/packages/EpiCloud&quot;&gt;EpiCloud PowerShell module&lt;/a&gt;&amp;nbsp;has two cmdlets for managing this,&amp;nbsp;&lt;strong&gt;Start-EpiDatabaseExport&lt;/strong&gt; can be used to start the export (it has a -Wait switch if you want it to wait until the export has finished before it returns). If you don&#39;t use &quot;-Wait&quot; there is also a cmdlet for fetching the export status called&amp;nbsp;&lt;strong&gt;Get-EpiDatabaseExport&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;More flexible API key management&lt;br /&gt;The API key management in the DXP Management Portal has been updated to allow for greater flexibility in how keys are created and can be used (it&#39;s now possible to assign access to environments on each key instead of having one key for each environment). For more information, see &lt;a href=&quot;/link/c2456bcf1ad24c29b7e1cfddd6df20a8.aspx&quot;&gt;the documentation&lt;/a&gt;.&lt;br /&gt;&lt;img src=&quot;/link/34abeaf419ba4c60809d58f106f106e8.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;General deployment updates&lt;/h2&gt;
&lt;p&gt;We&#39;ve also been working on a feature that is currently in&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;/link/b65125e7212142059e425ee2d086c652.aspx&quot;&gt;closed beta&lt;/a&gt;, namely Smooth deployments (aka. Zero Downtime Deployments). This feature aims to solve the problem of applying database updates without having to take the site offline.&lt;/p&gt;
&lt;p&gt;While this feature is still in closed beta, we&#39;ve added some improvements to the reset-process of deployments in general which can be used together with the maintenance page option in the DXP Management Portal. There are now three different recovery options after a deployment has completed it first stage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Roll-forward&lt;/strong&gt;&lt;br /&gt;We&#39;re now enabling you to start a new deployment while the maintenance page stays up if you want fix an unforeseen issue by code.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rollback code and database&lt;/strong&gt;&lt;br /&gt;It&#39;s now possible to automatically restore the database to the point in time before the database was updated as part of the reset process together with the previous version of the code (see the &quot;-RollbackDatabase&quot; switch of the Reset-EpiDeployment cmdlet in the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.powershellgallery.com/packages/EpiCloud&quot;&gt;EpiCloud PowerShell module&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rollback code only&lt;/strong&gt;&lt;br /&gt;Rollback only the code to the previous version (like it works today).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another update we&#39;ve made that it&#39;s possible to validate the restored slot before it&#39;s swapped back to receive live traffic (optional step available in the DXP Manangement Portal).&lt;/p&gt;
&lt;p&gt;More information about these recovery options and the upcoming Smooth deployment feature is available &lt;a href=&quot;/link/016387a70e524ec4beb5c25ba936b2b9.aspx&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What&#39;s next?&lt;/h2&gt;
&lt;p&gt;While these new features hopefully provide some significant improvements to the experience when developing for the DXP, we&#39;re definitely not done yet. We will soon look into more ways of accessing the blob storage in the different environments, harmonizing the functionality between the DXP Management Portal UI and the deployment API, getting Smooth deployment ready for GA and more.&lt;/p&gt;
&lt;p&gt;Meanwhile, make sure you grab the latest version of the &lt;a href=&quot;https://www.powershellgallery.com/packages/EpiCloud&quot;&gt;EpiCloud PowerShell module&lt;/a&gt;&amp;nbsp;and look through the related documentation to these new and updated features:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/link/cecd04dddeea47f89a14d7f163913728.aspx&quot;&gt;Deployment API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/link/eb85a23d0c1843aaa36f121668e1059e.aspx&quot;&gt;Deploy using PowerShell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/link/016387a70e524ec4beb5c25ba936b2b9.aspx&quot;&gt;Smooth deployments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/link/8211485cf8254701b1af4f75a205040c.aspx&quot;&gt;DXP self-deployment guide&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And finally but definitely not least, please reach out to us with any feedback you might have!&lt;/p&gt;</id><updated>2020-04-28T05:37:51.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Azure DevOps and Episerver deployment API</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2019/10/azure-devops-and-episerver-deployment-api/" /><id>&lt;p&gt;With the release of the &lt;a href=&quot;/link/cecd04dddeea47f89a14d7f163913728.aspx&quot;&gt;Deployment API&lt;/a&gt;, it&#39;s now possible to fully integrate existing CI/CD pipeline solutions with a DXC project. This blog post is using Azure DevOps as an example, but it&#39;s of course possible to use other tools to achieve pretty much the same thing. This pipeline is only a suggestion so it can of course be tweaked to better match the requirements of the specific project as needed.&lt;/p&gt;
&lt;p&gt;If you want a quick start guide related to the API and how it can be accessed and used, &lt;a href=&quot;/link/8c86df96587141818ac16cd6ec7368ce.aspx&quot;&gt;this blog post&lt;/a&gt;&amp;nbsp;might be of interest as well!&lt;/p&gt;
&lt;h2&gt;Creating a code package&lt;/h2&gt;
&lt;p&gt;First step is to generate a package that follows the standard described &lt;a href=&quot;/link/03b842974cad4e589239047cedd4a963.aspx&quot;&gt;here&lt;/a&gt;. Your build process might vary slightly of course (for example the location of your nuget.config file), but an example yaml-file that works in Azure DevOps can be found in my fork of the alloy repo &lt;a href=&quot;https://github.com/AWahlqvist/alloy-mvc-template/blob/master/azure-pipelines.yml&quot;&gt;here&lt;/a&gt;. The goal is basically to produce the binaries needed by the web app and then zip them up and give the resulting package a name that complies with the naming convention described by the documentation linked above.&lt;/p&gt;
&lt;p&gt;Once the above pipeline has been ran, it will produce an artifact that can be used as a deployment package in the release pipeline:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/65e46b2e65954423a9af269636828299.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In this case, I&#39;ve configured this build to run on each new commit on the master branch.&lt;/p&gt;
&lt;h2&gt;Creating a release pipeline&lt;/h2&gt;
&lt;p&gt;It&#39;s now time to create the pipeline that will be used to deploy the code package we created and promote it through the DXC project environments. At an overview this pipeline looks like this:&lt;br /&gt;&lt;img src=&quot;/link/a5c2ebe5e20c4d60a4796a1b04ed1e50.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I&#39;ve chosen to automatically trigger this release pipeline each time a commit is made to master:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/5315727aad80454e8065258a760e3c17.aspx&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Uploading the package&lt;/h3&gt;
&lt;p&gt;The first step of the release pipeline is to upload the code package so it&#39;s available for the deployment API. This can be done in various ways, but here&#39;s an example that works on the built-in agents (for example vs2017-win2016) that are available in Azure DevOps):&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;$env:PSModulePath = &quot;C:\Modules\azurerm_6.7.0;&quot; + $env:PSModulePath

$rootPath = &quot;$env:System_DefaultWorkingDirectory\_AWahlqvist.alloy-mvc-template\DXC Deployment Package\&quot;

if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
    Install-Module EpiCloud -Scope CurrentUser -Force
}

$resolvedPackagePath = Get-ChildItem -Path $rootPath -Filter *.nupkg

$getEpiDeploymentPackageLocationSplat = @{
    ClientKey = &quot;$(Integration.ClientKey)&quot;
    ClientSecret = &quot;$(Integration.ClientSecret)&quot;
    ProjectId = &quot;$(ProjectId)&quot;
}

$packageLocation = Get-EpiDeploymentPackageLocation @getEpiDeploymentPackageLocationSplat

Add-EpiDeploymentPackage -SasUrl $packageLocation -Path $resolvedPackagePath.FullName&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first line makes sure that the PowerShell module required to upload the code package to blob storage is available (the Add-EpiDeploymentPackage cmdlet in the EpiCloud module requires that the AzureRm or the Az module exists). After that, I&#39;ve specified the path to my artifact folder where the code package exists so I&#39;ll be able to specify the path to the code package that I&#39;m about to upload.&lt;/p&gt;
&lt;p&gt;Since I&#39;m using shared infrastructure in Azure DevOps, the &lt;a href=&quot;/link/eb85a23d0c1843aaa36f121668e1059e.aspx&quot;&gt;EpiCloud PowerShell module&lt;/a&gt;&amp;nbsp;won&#39;t exist on the machine which is why I&#39;ve added logic to install that as needed.&lt;/p&gt;
&lt;p&gt;I&#39;ve also added a few pipeline variables that will be used in this pipeline:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/3af68a5e25b0406b86df61bee4967d6a.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In this case, I&#39;m using the credentials for the integration environment to be able to access the API and retrieve a upload location for the package (temporary link, which is why it will fetch a new one for each deployment), and then upload that package to the target blob storage account that is used to host the deployment packages for my DXC project. Most of these variables are probably self-explanatory, but it might be worth noting that you should set the ClientSecret as a &quot;secret variable&quot; to have it protected, and that you can set certain variables to be settable when a release is created (which could make sense for example the &quot;UseMaintenancePage&quot;-parameter).&lt;/p&gt;
&lt;p&gt;If this step runs successfully, we now have a code package uploaded and ready to be used in a deployment.&lt;/p&gt;
&lt;h3&gt;Deploy package to Integration&lt;/h3&gt;
&lt;p&gt;It&#39;s now time to deploy this package to the integration environment and verify that it works as expected. The steps included in this stage are these:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/b557341554544eb2bb17632cdc5f276f.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The first step, that deploys the code package to the integration slot looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;$rootPath = &quot;$env:System_DefaultWorkingDirectory\_AWahlqvist.alloy-mvc-template\DXC Deployment Package\&quot;

if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
    Install-Module EpiCloud -Scope CurrentUser -Force
}

$resolvedPackagePath = Get-ChildItem -Path $rootPath -Filter *.nupkg

$startEpiDeploymentSplat = @{
    DeploymentPackage = $resolvedPackagePath.Name
    ProjectId = &quot;$(ProjectId)&quot;
    Wait = $true
    TargetEnvironment = &#39;Integration&#39;
    UseMaintenancePage = $(UseMaintenancePage)
    ClientSecret = &quot;$(Integration.ClientSecret)&quot;
    ClientKey = &quot;$(Integration.ClientKey)&quot;
}

$deploy = Start-EpiDeployment @startEpiDeploymentSplat

$deploy

Write-Host &quot;##vso[task.setvariable variable=DeploymentId;]$($deploy.id)&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty much the same principle as the previous script. Worth noting is the last line which creates a variable that will be used to complete/reset this deployment later. This variable is also specified under &quot;Output Variables&quot; and &quot;Reference name&quot; for the job step:&lt;br /&gt;&lt;img src=&quot;/link/78e0829cb7694f61aa5b6df0388616e5.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The reset task is configured to only run if a previous task has failed (see Control Options -&amp;gt; Run this task) which will then reset the environment if the smoketest step failed. If it works however, the pipeline will instead proceed with completing the deployment using the following code:&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;$rootPath = &quot;$env:System_DefaultWorkingDirectory\_AWahlqvist.alloy-mvc-template\DXC Deployment Package\&quot;

if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
    Install-Module EpiCloud -Scope CurrentUser -Force
}

$completeEpiDeploymentSplat = @{
    ProjectId = &quot;$(ProjectId)&quot;
    Id = &quot;$env:DeploymentId&quot;
    Wait = $true
    ClientSecret = &quot;$(Integration.ClientSecret)&quot;
    ClientKey = &quot;$(Integration.ClientKey)&quot;
}

Complete-EpiDeployment @completeEpiDeploymentSplat&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It would now make sense to run some sort of (preferably automated) acceptance tests on the integration site, if those succeed, we&#39;re ready to move on to the next stage, Preproduction.&lt;/p&gt;
&lt;h3&gt;Deploy to Preproduction&lt;/h3&gt;
&lt;p&gt;This stage will be quite similar to the Integration stage, but just to visualize how this might look for a real project, we can imagine that we have the following steps:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/e9e3a0b171884fc6be53a7f97577c121.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The difference compared to the Integration stage is that the environment in Preproduction will be better equipped to handle load, so a performance test would make more sense to run in this environment compared to the Integration environment. Could also make sense to run some automated penetration tests at this stage.&lt;/p&gt;
&lt;p&gt;In my test project, I&#39;ve also configured a &quot;Post-deployment condition&quot;, this could for example be a QA lead that should approve the release before it leaves the Preproduction-stage, for demonstration purposes, I&#39;ve added myself as an approver:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/110ddc4537c44eb9b489bb58759d736d.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Note that &quot;&lt;a href=&quot;https://docs.microsoft.com/en-us/azure/devops/pipelines/release/approvals/?view=azure-devops&quot;&gt;Gates&lt;/a&gt;&quot; can also be used to for example trigger performance tests, penetration tests or just validate that other metrics are OK before leaving the Preproduction-stage.&lt;/p&gt;
&lt;h3&gt;Deploy to Production&lt;/h3&gt;
&lt;p&gt;For the production environment, I&#39;ve chosen to add &quot;Pre-deployment approvals&quot; before the deployment is started, again, just for demonstration purposes I&#39;ve added myself as the approver:&lt;br /&gt;&lt;img src=&quot;/link/58ac32681f434a67856577062ab22700.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The actual deployment steps for this stage look like this:&lt;br /&gt;&lt;img src=&quot;/link/f20a1e2a00a743cdbcb338b973ea9f72.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This allows the deployment to be validated before the swap to make sure it behaves as expected. Once it has been approved it&#39;s time to either reset (cancel the deployment) or complete the deployment (Go Live).&lt;/p&gt;
&lt;p&gt;Here I use a slightly different approach to fetch the deployment id compared to the previous stages. The &quot;Fetch deployment id&quot; step looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;$rootPath = &quot;$env:System_DefaultWorkingDirectory\_AWahlqvist.alloy-mvc-template\DXC Deployment Package\&quot;

if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
    Install-Module EpiCloud -Scope CurrentUser -Force
}

$getEpiDeploymentSplat = @{
    ClientSecret = &quot;$(Production.ClientSecret)&quot;
    ClientKey = &quot;$(Production.ClientKey)&quot;
    ProjectId = &quot;$(ProjectId)&quot;
}

$deploy = Get-EpiDeployment @getEpiDeploymentSplat | Where-Object { $_.Status -eq &#39;AwaitingVerification&#39; -and $_.parameters.targetEnvironment -eq &#39;Production&#39; }

if (-not $deploy) {
    throw &quot;Failed to locate a deployment to complete/reset!&quot;
}

Write-Host &quot;##vso[task.setvariable variable=DeploymentId;]$($deploy.id)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of using the deployment id returned from the Start-EpiDeployment cmdlet, I instead fetch deployments that has the status of &quot;AwaitingVerification&quot; for the Production environment. Both approaches have their pros and cons and fit different scenarios. An obvious risk with this approach might be that you can&#39;t be 100% sure you reset/complete the deployment started by the build but has the benefit of always finding the ID of an ongoing deployment if it exists if that&#39;s the goal.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;I hope this blog post has provided some guidance on how the new API and corresponding PowerShell module can be used to setup a CI/CD pipeline for your DXC project, if you have any questions or thoughts, please feel free to reach out in the comment section below!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/e3a82f91baf844dc9a4235e3d5098cd7.aspx&quot; /&gt;&lt;/p&gt;</id><updated>2019-10-29T20:02:30.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Using routing rules to validate a site before go live/swap (DXC Service)</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2019/3/using-routing-rules-to-validate-a-site-before-go-liveswap-dxc-service/" /><id>&lt;p&gt;During a deployment in DXC Service a temporary slot is created where the new version of the site is pushed, prepared and &lt;a href=&quot;/link/ce80e6dd766c40aeaa9be6b4f5d88430.aspx&quot;&gt;warmed up&lt;/a&gt;. If everything looks good during the manual validation step, it will finally be swapped with the previous version of the web app.&lt;/p&gt;
&lt;p&gt;The new version of the site is usually accessible via the following link:&lt;br /&gt;&lt;span&gt;https://{&lt;/span&gt;&lt;span class=&quot;nolink&quot;&gt;webappname}-slot.dxcloud.episerver.net&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The recommendation is to have a default site with a &quot;*&quot; binding or at least add the hostname above in the site bindings of the CMS (see &quot;&lt;a href=&quot;/link/b80fa5168ac24c0b8a637eb779f09d42.aspx&quot;&gt;Before going live&lt;/a&gt;&quot;) to make this URL work, but what if you need to validate more sites before you feel comfortable swapping the deployment slot? Or if this binding just isn&#39;t added for some reason?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Consider the following setup as an example:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/1b499198e6c04be08be444a55b8ccf19.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When trying to browse this site through the slot-address mentioned above, it would just respond with a 404 like this:&lt;br /&gt;&lt;img src=&quot;/link/bfb6c7afc9ab4f388b999744099137ff.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Some implementations might also expect certain host headers to be used which could make validation of the slot quite tricky.&lt;/p&gt;
&lt;p&gt;This is where routing rules can help!&lt;/p&gt;
&lt;h3&gt;So what are routing rules? How can I use them?&lt;/h3&gt;
&lt;p&gt;Routing rules is a Azure feature that makes it possible to route traffic via one of the hostnames assigned to the web app to one of its slots. During DXC Service deployments, the deployment engine will automatically attempt to configure routing rules for the slot so that any of the assigned hostnames can be tested in the slot, this is done just before the &quot;warmup step&quot; in the deployment. Before the slot is swapped (the complete/go live step), these rules are removed again. The rule is configured so that no production traffic is routed to the slot (100% to &quot;production slot&quot; and 0% to the deployment slot) while still allowing the routing rule to be used if a special cookie is added.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using a cookie to browse the slot using a custom hostname&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While there are actually two ways of triggering this behavior, using a cookie is the most reliable way. You simply need to add a cookie named &quot;x-ms-routing-name&quot; to your browser session with the value of the slot you want to browse (which for DXC Service deployments will be &quot;slot&quot;).&lt;/p&gt;
&lt;p&gt;The following example shows how it can be achieved in Chrome:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Browse the hostname you want to use, for example www.alloytech.biz (you might want to use &quot;incognito&quot;/&quot;private&quot;-mode to avoid having this cookie stored in your normal session after you&#39;ve validated the slot, or make sure you remember to remove it)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Press F12, go the the &quot;Application&quot;-tab and expand &quot;Cookies on the left hand side:&lt;br /&gt;&lt;img src=&quot;/link/186ae60fb92949ddb79ac029661334a4.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Double-click under the last cookie in the list and enter &quot;x-ms-routing-name&quot; as the cookie name:&lt;br /&gt;&lt;img src=&quot;/link/a49b05113ec44ffa935bf9c10d126b71.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Enter the slotname in the &quot;value&quot; field for the new cookie, for DXC Service deployments, the name should simply be &quot;slot&quot;:&lt;br /&gt;&lt;img src=&quot;/link/bb9efb8b40404cca96a76073d7a852f1.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Press Enter, and refresh the page and you will be browsing the slot using the hostname you entered in step 1!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It is also possible to use a query string to trigger this behavior, you simply add&amp;nbsp;&quot;?x-ms-routing-name=slot&quot; to the address, however, this method isn&#39;t as reliable since requests issued by scripts on the site could still be routed to the &quot;production slot&quot;, so it&#39;s recommended to use the &quot;cookie method&quot; instead.&lt;/p&gt;
&lt;h3&gt;How are routing rules used during deployments then?&lt;/h3&gt;
&lt;p&gt;During deployments in DXC Service, routing rules are used to check the status of &lt;a href=&quot;/link/ce80e6dd766c40aeaa9be6b4f5d88430.aspx&quot;&gt;the warmup process&lt;/a&gt;, the deployment engine will look for a hostname to use in the application initialization-section of Web.config.&lt;/p&gt;
&lt;p&gt;If you want to check what hostname was used to validate the slot during the deployment you can check the deployment output log, after each site in the deployment has been warmed up the results are posted to the log which includes a &quot;ManualValidationLink&quot;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/e1d3a7255c314edc9866386f05da23d8.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This link can be used directly in the browser, but since the cookie method is more reliable, it&#39;s recommended to use that instead (but you could of course still find and copy the cookie name and value from this link!)&lt;/p&gt;</id><updated>2019-03-26T13:02:11.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Using routing rules to validate a site before go live/swap (DXC Service)</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2019/3/using-routing-rules-to-validate-a-site-before-go-liveswap-dxc-service/" /><id>&lt;p&gt;During a deployment in DXC Service a temporary slot is created where the new version of the site is pushed, prepared and &lt;a href=&quot;/link/ce80e6dd766c40aeaa9be6b4f5d88430.aspx&quot;&gt;warmed up&lt;/a&gt;. If everything looks good during the manual validation step, it will finally be swapped with the previous version of the web app.&lt;/p&gt;
&lt;p&gt;The new version of the site is usually accessible via the following link:&lt;br /&gt;&lt;span&gt;https://{&lt;/span&gt;&lt;span class=&quot;nolink&quot;&gt;webappname}-slot.dxcloud.episerver.net&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;The recommendation is to have a default site with a &quot;*&quot; binding or at least add the hostname above in the site bindings of the CMS (see &quot;&lt;a href=&quot;/link/b80fa5168ac24c0b8a637eb779f09d42.aspx&quot;&gt;Before going live&lt;/a&gt;&quot;) to make this URL work, but what if you need to validate more sites before you feel comfortable swapping the deployment slot? Or if this binding just isn&#39;t added for some reason?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Consider the following setup as an example:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/1b499198e6c04be08be444a55b8ccf19.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When trying to browse this site through the slot-address mentioned above, it would just respond with a 404 like this:&lt;br /&gt;&lt;img src=&quot;/link/bfb6c7afc9ab4f388b999744099137ff.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Some implementations might also expect certain host headers to be used which could make validation of the slot quite tricky.&lt;/p&gt;
&lt;p&gt;This is where routing rules can help!&lt;/p&gt;
&lt;h3&gt;So what are routing rules? How can I use them?&lt;/h3&gt;
&lt;p&gt;Routing rules is a Azure feature that makes it possible to route traffic via one of the hostnames assigned to the web app to one of its slots. During DXC Service deployments, the deployment engine will automatically attempt to configure routing rules for the slot so that any of the assigned hostnames can be tested in the slot, this is done just before the &quot;warmup step&quot; in the deployment. Before the slot is swapped (the complete/go live step), these rules are removed again. The rule is configured so that no production traffic is routed to the slot (100% to &quot;production slot&quot; and 0% to the deployment slot) while still allowing the routing rule to be used if a special cookie is added.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using a cookie to browse the slot using a custom hostname&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While there are actually two ways of triggering this behavior, using a cookie is the most reliable way. You simply need to add a cookie named &quot;x-ms-routing-name&quot; to your browser session with the value of the slot you want to browse (which for DXC Service deployments will be &quot;slot&quot;).&lt;/p&gt;
&lt;p&gt;The following example shows how it can be achieved in Chrome:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Browse the hostname you want to use, for example www.alloytech.biz (you might want to use &quot;incognito&quot;/&quot;private&quot;-mode to avoid having this cookie stored in your normal session after you&#39;ve validated the slot, or make sure you remember to remove it)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Press F12, go the the &quot;Application&quot;-tab and expand &quot;Cookies on the left hand side:&lt;br /&gt;&lt;img src=&quot;/link/186ae60fb92949ddb79ac029661334a4.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Double-click under the last cookie in the list and enter &quot;x-ms-routing-name&quot; as the cookie name:&lt;br /&gt;&lt;img src=&quot;/link/a49b05113ec44ffa935bf9c10d126b71.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Enter the slotname in the &quot;value&quot; field for the new cookie, for DXC Service deployments, the name should simply be &quot;slot&quot;:&lt;br /&gt;&lt;img src=&quot;/link/bb9efb8b40404cca96a76073d7a852f1.aspx&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Press Enter, and refresh the page and you will be browsing the slot using the hostname you entered in step 1!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It is also possible to use a query string to trigger this behavior, you simply add&amp;nbsp;&quot;?x-ms-routing-name=slot&quot; to the address, however, this method isn&#39;t as reliable since requests issued by scripts on the site could still be routed to the &quot;production slot&quot;, so it&#39;s recommended to use the &quot;cookie method&quot; instead.&lt;/p&gt;
&lt;h3&gt;How are routing rules used during deployments then?&lt;/h3&gt;
&lt;p&gt;During deployments in DXC Service, routing rules are used to check the status of &lt;a href=&quot;/link/ce80e6dd766c40aeaa9be6b4f5d88430.aspx&quot;&gt;the warmup process&lt;/a&gt;, the deployment engine will look for a hostname to use in the application initialization-section of Web.config.&lt;/p&gt;
&lt;p&gt;If you want to check what hostname was used to validate the slot during the deployment you can check the deployment output log, after each site in the deployment has been warmed up the results are posted to the log which includes a &quot;ManualValidationLink&quot;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/e1d3a7255c314edc9866386f05da23d8.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This link can be used directly in the browser, but since the cookie method is more reliable, it&#39;s recommended to use that instead (but you could of course still find and copy the cookie name and value from this link!)&lt;/p&gt;</id><updated>2019-03-26T13:02:11.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Web application warmup during DXC Service deployments</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2019/3/web-application-warmup-during-dxc-service-deployments/" /><id>&lt;p&gt;When deploying through the DXC Service Management Portal, warmup is both configured (when needed) and tested automatically as a part of the deployment. Since it&#39;s usually the most time-consuming part of a deployment, this blog post is aimed at providing a few more details on what&#39;s going on at this step and provide some information on how it can be done as quickly as possible.&lt;/p&gt;
&lt;h3&gt;How is warm up configured for sites in DXC Service?&lt;/h3&gt;
&lt;p&gt;During the first part of the deployment where code is copied and transformations are applied, the deployment engine will check if an &lt;a href=&quot;https://docs.microsoft.com/en-us/iis/get-started/whats-new-in-iis-8/iis-80-application-initialization&quot;&gt;applicationInitialization&lt;/a&gt;-section exists in Web.config, if it doesn&#39;t, it will be automatically created (more information about this is available &lt;a href=&quot;/link/947015c1d514443b9d33caa03b953c2c.aspx&quot;&gt;here&lt;/a&gt;). Because of the way Application Initialization works on the underlying web server, some further configuration related to rewrite rules and redirects will be applied if needed as well to ensure that the warmup requests will be as effective as possible (a redirect response will be accepted in the same way as a 200 OK response by application initialization (and not &quot;followed&quot;), which means that a simple http to https redirect could render the whole&amp;nbsp;application initialization configuration almost useless, therefor, rewrite rules are configured so that the application initialization requests are excluded from any redirects).&lt;/p&gt;
&lt;p&gt;Once the &quot;code copy&quot;-part of the deployment has finished, the warmup process will begin.&lt;/p&gt;
&lt;h3&gt;What is happening during the warm up step?&lt;/h3&gt;
&lt;p&gt;Autoscaling is first temporarily disabled before any warmup starts (making the current number of instances of the web app &quot;fixed&quot;) to avoid any unnecessary scaleouts that could otherwise be triggered by the warmup process. After that the first part of a Azure web app &quot;swap with preview&quot; is initiated which ensures that the deployment slot created during the deployment process will be ready to receive production traffic after the swap is completed and avoid any restarts of the web app.&lt;/p&gt;
&lt;p&gt;Once that has finished the application initialization process will begin automatically within each individual instance of the web application. On top of this, the deployment engine will also perform a couple of checks to try to validate that this process works as expected. First, each individual instance&#39;s&amp;nbsp;&lt;a href=&quot;https://docs.microsoft.com/en-us/azure/app-service/overview-local-cache&quot;&gt;local cache&lt;/a&gt; status is verified to ensure the best possible performance and stability of the web app once it&#39;s swapped.&lt;/p&gt;
&lt;p&gt;The application initialization section is also analyzed to find a suitable hostname that can be used to poll the web app and its instances in the slot and check its response (whenever possible, a feature called &lt;a href=&quot;/link/6ba35c7a2dde44daacc95c4fd8d42fe8.aspx&quot;&gt;routing rules&lt;/a&gt; is utilized to be able to use a &quot;real&quot; hostname to reach the deployment slot). Some of the things analyzed in the response are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the header &quot;X-AppInit-WarmingUp&quot; is returned, it means that the Application Initialization engine is still running&lt;/li&gt;
&lt;li&gt;Which web app instance that sent the response, if the response doesn&#39;t come from the same instance as the request was sent to, it indicates that the load balancer in Azure has redirected the request because&amp;nbsp;the Application Initialization engine is still running&lt;/li&gt;
&lt;li&gt;If the request times out, or if the instance responds with errors, it could potentially indicate that&amp;nbsp;the Application Initialization engine is still running and therefor the process will keep polling the site until the response changes or if a timeout value is met&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once all instances of the web app have been validated successfully (or if the timeout value has been met), the deployment will continue with re-enabling autoscaling and allow the site to be swapped after a manual validation.&lt;/p&gt;
&lt;h3&gt;What can be done to speed this up?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Local cache&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When it comes to local cache, the only thing that can be done to make this as quick as possible is to keep the web app file size as small as possible, it&#39;s otherwise an internal process in Azure that could potentially be affected by for example network congestion in the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;Local cache can sometimes take only a few seconds to be ready, but it could also take several minutes. There is no guarantee that it will be ready on all instances at the same time, which is why the deployment engine will check all of them individually.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application Initialization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The amount of time the application initialization process takes is highly dependent on the site and how quickly it starts, it&#39;s also affected by the number of links that have been added to the applicationInitialization-section of course, especially if each page takes a significant time to load (it&#39;s run sequentially).&lt;/p&gt;
&lt;p&gt;Configuring a minimal&amp;nbsp;applicationInitialization-section to save time during deployment is of course not recommended since that could cause new instances to be slow in production instead, but it could of course potentially be a balance between being able to scale out faster or making sure that every single page on the web app has been warmed up.&lt;/p&gt;
&lt;p&gt;The logic used to create this section automatically during deployments have been tried and tested over thousands of deployments and has the primary goal of making sure that scale outs and potential restarts of instances will be as seamless as possible, so it&#39;s not recommended to create this section manually.&lt;/p&gt;
&lt;p&gt;Making sure that the site in the slot is able to respond with &quot;200 OK&quot; however could save several minutes since it allows the deployment engine to actually detect if the&amp;nbsp;application initialization process has finished (the &quot;X-AppInit-WarmingUp&quot; header is only returned on succesful responses) instead of letting it try to validate this until it hits the timeout.&lt;/p&gt;
&lt;p&gt;At the time of writing this blog post, the timeout values are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If no warmup is detected&lt;/strong&gt; (for example if the site just keeps responding with errors), it will wait for up to &lt;strong&gt;10 minutes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If warmup is detected&lt;/strong&gt; for at least one instance, it will wait for a maximum time of &lt;strong&gt;25 minutes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Why does this have to finish before I can swap the site?&lt;/h3&gt;
&lt;p&gt;As part of the swap process Azure also tries to validate the slot before the swap is made, these checks includes things like warmup and local cache to ensure that the new slot will behave as it&#39;s supposed to after the swap. If these checks fail, it will simply block the swap request so there isn&#39;t really any point in trying until the site is ready.&lt;/p&gt;
&lt;h3&gt;How can I know what took so much time in my latest deployment?&lt;/h3&gt;
&lt;p&gt;The details of the warmup process for each individual instance is logged in the detailed deployment log which can be accessed by first opening the output log of the deployment and then click the &quot;Get Detailed Log&quot;-button (see &quot;Deployment job log output&quot; in &lt;a href=&quot;/link/8211485cf8254701b1af4f75a205040c.aspx#joblog&quot;&gt;this article&lt;/a&gt;).&lt;/p&gt;</id><updated>2019-03-26T10:35:06.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Web application warmup during DXC Service deployments</title><link href="https://world.optimizely.com/blogs/anders-wahlqvist/dates/2019/3/web-application-warmup-during-dxc-service-deployments/" /><id>&lt;p&gt;When deploying through the DXC Service Management Portal, warmup is both configured (when needed) and tested automatically as a part of the deployment. Since it&#39;s usually the most time-consuming part of a deployment, this blog post is aimed at providing a few more details on what&#39;s going on at this step and provide some information on how it can be done as quickly as possible.&lt;/p&gt;
&lt;h3&gt;How is warm up configured for sites in DXC Service?&lt;/h3&gt;
&lt;p&gt;During the first part of the deployment where code is copied and transformations are applied, the deployment engine will check if an &lt;a href=&quot;https://docs.microsoft.com/en-us/iis/get-started/whats-new-in-iis-8/iis-80-application-initialization&quot;&gt;applicationInitialization&lt;/a&gt;-section exists in Web.config, if it doesn&#39;t, it will be automatically created (more information about this is available &lt;a href=&quot;/link/d3ec9948a8d74f6f83a730d44f337783.aspx&quot;&gt;here&lt;/a&gt;). Because of the way Application Initialization works on the underlying web server, some further configuration related to rewrite rules and redirects will be applied if needed as well to ensure that the warmup requests will be as effective as possible (a redirect response will be accepted in the same way as a 200 OK response by application initialization (and not &quot;followed&quot;), which means that a simple http to https redirect could render the whole&amp;nbsp;application initialization configuration almost useless, therefor, rewrite rules are configured so that the application initialization requests are excluded from any redirects).&lt;/p&gt;
&lt;p&gt;Once the &quot;code copy&quot;-part of the deployment has finished, the warmup process will begin.&lt;/p&gt;
&lt;h3&gt;What is happening during the warm up step?&lt;/h3&gt;
&lt;p&gt;Autoscaling is first temporarily disabled before any warmup starts (making the current number of instances of the web app &quot;fixed&quot;) to avoid any unnecessary scaleouts that could otherwise be triggered by the warmup process. After that the first part of a Azure web app &quot;swap with preview&quot; is initiated which ensures that the deployment slot created during the deployment process will be ready to receive production traffic after the swap is completed and avoid any restarts of the web app.&lt;/p&gt;
&lt;p&gt;Once that has finished the application initialization process will begin automatically within each individual instance of the web application. On top of this, the deployment engine will also perform a couple of checks to try to validate that this process works as expected. First, each individual instance&#39;s&amp;nbsp;&lt;a href=&quot;https://docs.microsoft.com/en-us/azure/app-service/overview-local-cache&quot;&gt;local cache&lt;/a&gt; status is verified to ensure the best possible performance and stability of the web app once it&#39;s swapped.&lt;/p&gt;
&lt;p&gt;The application initialization section is also analyzed to find a suitable hostname that can be used to poll the web app and its instances in the slot and check its response (whenever possible, a feature called &lt;a href=&quot;/link/6ba35c7a2dde44daacc95c4fd8d42fe8.aspx&quot;&gt;routing rules&lt;/a&gt; is utilized to be able to use a &quot;real&quot; hostname to reach the deployment slot). Some of the things analyzed in the response are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the header &quot;X-AppInit-WarmingUp&quot; is returned, it means that the Application Initialization engine is still running&lt;/li&gt;
&lt;li&gt;Which web app instance that sent the response, if the response doesn&#39;t come from the same instance as the request was sent to, it indicates that the load balancer in Azure has redirected the request because&amp;nbsp;the Application Initialization engine is still running&lt;/li&gt;
&lt;li&gt;If the request times out, or if the instance responds with errors, it could potentially indicate that&amp;nbsp;the Application Initialization engine is still running and therefor the process will keep polling the site until the response changes or if a timeout value is met&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once all instances of the web app have been validated successfully (or if the timeout value has been met), the deployment will continue with re-enabling autoscaling and allow the site to be swapped after a manual validation.&lt;/p&gt;
&lt;h3&gt;What can be done to speed this up?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Local cache&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When it comes to local cache, the only thing that can be done to make this as quick as possible is to keep the web app file size as small as possible, it&#39;s otherwise an internal process in Azure that could potentially be affected by for example network congestion in the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;Local cache can sometimes take only a few seconds to be ready, but it could also take several minutes. There is no guarantee that it will be ready on all instances at the same time, which is why the deployment engine will check all of them individually.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application Initialization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The amount of time the application initialization process takes is highly dependent on the site and how quickly it starts, it&#39;s also affected by the number of links that have been added to the applicationInitialization-section of course, especially if each page takes a significant time to load (it&#39;s run sequentially).&lt;/p&gt;
&lt;p&gt;Configuring a minimal&amp;nbsp;applicationInitialization-section to save time during deployment is of course not recommended since that could cause new instances to be slow in production instead, but it could of course potentially be a balance between being able to scale out faster or making sure that every single page on the web app has been warmed up.&lt;/p&gt;
&lt;p&gt;The logic used to create this section automatically during deployments have been tried and tested over thousands of deployments and has the primary goal of making sure that scale outs and potential restarts of instances will be as seamless as possible, so it&#39;s not recommended to create this section manually.&lt;/p&gt;
&lt;p&gt;Making sure that the site in the slot is able to respond with &quot;200 OK&quot; however could save several minutes since it allows the deployment engine to actually detect if the&amp;nbsp;application initialization process has finished (the &quot;X-AppInit-WarmingUp&quot; header is only returned on succesful responses) instead of letting it try to validate this until it hits the timeout.&lt;/p&gt;
&lt;p&gt;At the time of writing this blog post, the timeout values are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If no warmup is detected&lt;/strong&gt; (for example if the site just keeps responding with errors), it will wait for up to &lt;strong&gt;10 minutes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If warmup is detected&lt;/strong&gt; for at least one instance, it will wait for a maximum time of &lt;strong&gt;25 minutes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Why does this have to finish before I can swap the site?&lt;/h3&gt;
&lt;p&gt;As part of the swap process Azure also tries to validate the slot before the swap is made, these checks includes things like warmup and local cache to ensure that the new slot will behave as it&#39;s supposed to after the swap. If these checks fail, it will simply block the swap request so there isn&#39;t really any point in trying until the site is ready.&lt;/p&gt;
&lt;h3&gt;How can I know what took so much time in my latest deployment?&lt;/h3&gt;
&lt;p&gt;The details of the warmup process for each individual instance is logged in the detailed deployment log which can be accessed by first opening the output log of the deployment and then click the &quot;Get Detailed Log&quot;-button (see &quot;Deployment job log output&quot; in &lt;a href=&quot;/link/9b6c9ddb7ae54ebcbe1857d4f30ae984.aspx&quot;&gt;this article&lt;/a&gt;).&lt;/p&gt;</id><updated>2019-03-26T10:35:06.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>