An App Service Environment is a comfortable place to be. It runs, it is managed, and the team that set it up has long since moved on to other work. The question is not whether it works. The question is whether the way it is deployed and hosted still matches the way the business operates now.
That was the question at a regulated electric and gas utility operating in two states. The two state businesses were being merged into one operation, and the systems had to follow. Customer service was unified onto Twilio. Deployments were put under Terraform and Bicep. And the App Service Environment was moved to Azure Kubernetes Service (AKS).
A migration like this fails when it is treated as a lift-and-shift: the same application, the same configuration, the same habits, on a different platform. AKS is not a newer version of an App Service Environment. It is a different way of running things, and the move has to be planned as one.
The first thing to settle is networking. An App Service Environment is isolated by design. In AKS, isolation is something you build: namespaces, network policies, private clusters, ingress that only exposes what should be exposed. That work is not glamorous, and it is the work that decides whether the migration is a success or a long series of incidents. We mapped the traffic before we moved anything — what talks to what, on which port, and what happens when one of those things is down.
The second thing is deployments. Putting deployments under Terraform and Bicep is not a matter of writing the same settings in a different language. It is a matter of deciding what a deployment is: a versioned, reviewable change, applied the same way every time, by the same pipeline, with the same checks. A deployment that depends on a person remembering a setting in a portal is not a deployment. It is a hope.
Terraform and Bicep each have a place here. Terraform describes the Azure resources — the cluster, the networking, the identities. Bicep describes the Azure-native pieces in the language Azure itself understands. The point is not which tool wins. The point is that the infrastructure is written down, reviewed as a pull request, and applied by a pipeline, so the environment that runs in production is the environment that is in the repository.
The third thing is the application itself. An application that ran on an App Service Environment expects certain things: a platform that handles scaling, a platform that handles health checks, a platform that handles restarts. In AKS, those things are the application's job, expressed in its manifests: resource requests and limits, liveness and readiness probes, pod disruption budgets. That is not a burden. It is a statement, in the repository, of what the application needs to run well.
We moved the utility's systems in that order: networking first, deployments second, the application last. Each step was a pull request, reviewed by a senior engineer, with tests and linting, and released with a note on what changed. Nothing was moved in a single weekend, and nothing was moved without a way back.
The result is not a platform that is newer. It is a platform that the team can operate. The infrastructure is in the repository. The deployments are repeatable. The application declares what it needs. And when the next change comes — a new service, a new region, a new requirement from a regulator — the change is a pull request, not a project.
That is what a deliberate migration buys. Not a new logo on the same setup, but a setup that can be changed, reviewed, and trusted, by the people who have to run it.