Subchapter 42.47
references/services/functions/consumption-to-flex/windows/workflow.mdMarkdown28 KBView on GitHub
Source: Azure Functions Consumption Plan (Y1/Dynamic) on Windows Target: Azure Functions Flex Consumption Plan (FC1/FlexConsumption) : Windows → Linux (Flex Consumption is Linux-based) :
⚠️ This is a Windows-to-Linux migration, not just a plan change. Flex Consumption is Linux-based. Apps with Windows-specific dependencies, in-process .NET, .NET Framework targeting, or Windows-RID deployment packages must be prepared before migration. See Known Limitations and Migration Blockers.
Before running any discovery or Azure command, read the ordered ### Phase headings in this workflow and the ordered workflow-unit table in automation.md. Present a concise user-facing summary in that order, combining implementation units under their corresponding phases. Do not maintain or infer a separate hard-coded step list.
State that the source app remains read-only during assessment and replication. Every source-changing cutover, rollback, or cleanup action requires a separate, immediate approval. After presenting the plan, confirm the source app and Flex Consumption target plan with the user before continuing.
The source app is read-only throughout assessment and replication. Before any cutover, rollback, or cleanup command that changes the source app’s settings, triggers, state, deployment, bindings, or existence, the skill must use ask_user to describe the exact action and obtain explicit approval. Approval is specific to that action and cannot be reused for later source changes.
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING/WEBSITE_CONTENTSHARE); Flex uses blob-based One Deploy (immutable zip packages in Azure Blob Storage).az functionapp flex-migration does not support Windows — all migration steps use raw CLI commands (see automation.md).resource-graph extension: az extension add --name resource-graphjq tool for JSON processing| Stack ID | Language | Supported? |
|---|---|---|
dotnet-isolated (.NET 8+) | .NET isolated worker, .NET 8+ | ✅ Yes — if no Windows-only dependencies and not published with a Windows RID |
dotnet-isolated (.NET Framework) | .NET isolated worker targeting net4x | ❌ No — .NET Framework runtime not present on Linux; must retarget to .NET 8+ |
dotnet | .NET in-process model | ❌ No — not supported on Flex; must migrate to isolated worker model first |
node | JavaScript/TypeScript | ✅ Yes |
java | Java | ✅ Yes |
python | Python | ✅ Yes |
powershell | PowerShell | ⚠️ Review — Windows-only modules (WMI, registry, COM interop) will not work on Linux |
go | Go (Preview) | ✅ Yes — if the handler and native dependencies are built for Linux |
custom | Custom handlers | ⚠️ Review — handler binary must be Linux-compatible |
| Feature | Status | Action Required |
|---|---|---|
| Deployment slots | ❌ Not supported | Consolidate to production slot or rearchitect to separate apps |
| TLS/SSL certificates | ⚠️ Site-scoped certificates in preview | Re-add used certificates after migration, verify the per-app limits, and update code to use Linux certificate file paths |
| Blob trigger (polling) | ❌ EventGrid source only | Convert LogsAndContainerScan → EventGrid; create event subscription |
Disable setting for function names containing - | ❌ Not supported on Linux | Isolate the target dependency, rename/repackage the function, use a source-first deployment cutover, or explicitly accept active-trigger risk |
| Azure Government | ❌ Not available | Cannot migrate yet |
| MSDeploy / FTP / Kudu git deploy | ❌ Not supported | Switch to az functionapp deploy or func azure functionapp publish |
| PowerShell managed dependencies | ❌ Not supported | Package all required modules in the app-root Modules folder before deployment; verify Linux compatibility. requirements.psd1 alone doesn’t install modules on Flex Consumption. See PowerShell dependency management (opens in a new tab). |
| Issue | How to Detect | Action Required |
|---|---|---|
| .NET in-process model | FUNCTIONS_WORKER_RUNTIME=dotnet app setting | Migrate to isolated worker model — requires code changes (different NuGet packages, Program.cs startup) |
.NET Framework targeting (net4x) | .csproj target framework | Retarget to .NET 8+ — may require replacing Framework-only APIs and NuGet packages |
| Windows-only NuGet packages (GDI+, COM, P/Invoke) | Assembly/package scan (heuristic) | Replace with cross-platform alternatives, or migrate to Elastic Premium on Windows |
| Windows RID deployment package | runtimes/win-x64/ present without linux-x64 in package | Republish without a RID (framework-dependent) or with -r linux-x64 |
| Path separator / case sensitivity | Code review | Replace \ path construction with Path.Combine(); fix case-sensitive file references |
| PowerShell Windows-only modules (WMI, registry, COM) | requirements.psd1 module imports | Replace with cross-platform alternatives or remove |
| Windows certificate store access | Code review | Migrate to file-based certificate loading |
| Unsupported language runtime version | Site config | Upgrade to a supported version (opens in a new tab) |
| App region not supported by Flex | Region vs. Flex availability list | Wait for regional availability, or relocate the app |
💡 Elastic Premium escape hatch: Apps with hard Windows dependencies that cannot be removed can migrate to Elastic Premium on Windows (opens in a new tab) as an alternative. This changes the hosting plan without requiring an OS migration.
The new Flex Consumption app needs a globally unique name. The skill defaults to <source>-flex — e.g. if your source app is test-app, the new app will be test-app-flex. This is short, self-documenting, and signals the SKU change.
Two modes are supported. State your preference in your initial migration request:
| Mode | How to invoke | Resulting name |
|---|---|---|
| Default suffix (default) | Just say “migrate my function app” | <source>-flex |
| Custom name | “migrate my function app as <name>“ or “… named <name>“ | The name you provide |
⚠️ Skill instruction: Before executing Step 4b in automation.md, announce the proposed name to the user, e.g. “I’ll create the new Flex app as
test-app-flexin resource grouptest-app_group(regionwestus2). Say so if you’d prefer a different name.” This gives the user a chance to course-correct without a blocking prompt.
💡 Constraints (from the underlying MS Learn create flow (opens in a new tab)): globally unique in Azure (becomes
<APP_NAME>.azurewebsites.net), 2–60 characters, alphanumerics + hyphens, must start with a letter, no consecutive hyphens. If the default<source>-flexwould exceed 60 chars or collides with an existing app, fall back to a shortened suffix (e.g.<source>-fc) and announce that to the user.
The new Flex Consumption app needs a storage account bound at creation time. The skill defaults to reusing the source app’s existing storage account — the same default as az functionapp flex-migration on Linux. This is the lowest-friction option because there is no new storage resource to manage. Flex configures deployment storage on the target rather than reusing the source app’s Windows content-share settings.
Three modes are supported. State your preference in your initial migration request — the skill will detect it and set the binding accordingly. Think of these as CLI-style flags:
| Mode | How to invoke | When to use |
|---|---|---|
| Reuse source storage (default) | Just say “migrate my function app” | Most migrations. No isolation needed between source and target. |
| Create new storage | “migrate my function app with a new storage account“ or “… and create a new storage account“ | You want isolated storage for blast-radius, compliance, or test/prod separation. |
| Use a specific existing account | “migrate my function app using storage account <name>“ | You already have a target account provisioned (e.g. via IaC or central platform team). |
⚠️ Skill instruction: Before executing Step 4a/4b in automation.md, announce the storage choice to the user, e.g. “I’ll reuse your existing storage account
foofor the new Flex app. Say so if you’d prefer a new isolated account or a different existing one.” This gives the user a chance to course-correct without a blocking prompt.
Initialize and maintain <UPGRADE_DIR>/upgrade-status.md using Migration Progress. Derive its workflow snapshot from the current scenario and automation headings, and show the current phase, substep, description, and state in chat at every transition; do not use a percentage.
Run all checks from assessment.md. Since az functionapp flex-migration does not support Windows, eligibility is determined manually — use Step 1 and Step 2 in automation.md to identify candidate apps and run compatibility checks.
Upgrade Readiness.Collect all settings and configurations from the existing app before creating the new one. See Step-by-step scripts in automation.md:
Execute Steps 4a–4l from automation.md. Each sub-step handles a discrete part of the migration:
💡 Use Microsoft Entra ID + managed identities instead of connection strings when creating the new app.
Enterprise subscriptions commonly enforce policies blocking local auth. Configure identity-based access:
AzureWebJobsStorage* settings.Authorization=AAD when the source already uses it; otherwise treat conversion as optional post-migration hardeningmanagedIdentityClientId explicitlySteps 4a–4i migrate application configuration; Step 4f.auth handles built-in authentication; Steps 4j–4k establish trigger safety and verify monitoring; Step 4l records the access-key strategy. Verify the results and manually configure anything not covered by those steps (see automation.md):
⚠️ Code is NOT automatically migrated. The new app is created with config only — you must deploy code separately.
⚠️ If Step 4b storage authentication preflight or identity-first provisioning remains blocked, do not deploy code. Required storage identities, role assignments, and access validation cannot be deferred.
⚠️ If source app settings were deferred in Step 4c, deployment is blocked until the user confirms all required application-specific target settings are configured. The skill may inspect names, but never setting values.
⚠️ If built-in authentication was deferred in Step 4f.auth, deployment is blocked. The source authentication boundary must be recreated and verified before application code is placed on the target.
Use ask_user to present these options:
Your new Flex Consumption app
<NEW_APP_NAME>has been created and configured. Now we need to deploy your function code. How would you like to proceed?
- Update CI/CD pipeline — I’ll help you update your Azure Pipelines or GitHub Actions workflow to target the new app
- Deploy from local project — I’ll run
func azure functionapp publish <NEW_APP_NAME>from your project directory- Deploy existing package — I’ll deploy the package we downloaded earlier from the original app
After user selects an option, execute the corresponding deployment method from automation.md — Step 5.
After deployment synchronizes all functions, execute Step 5a. When preservation was selected, copy and verify source host and HTTP-function keys before any HTTP validation. System and master keys remain target-generated.
✅ If Step 4j disablement was approved and no risky hyphenated non-HTTP function was approved for active deployment, only HTTP endpoints will be live after deployment and per-function cutover happens in Phase 6.
✅ If Step 4j was skipped because the target is fully isolated, deploy without per-function disable settings and validate only against those isolated dependencies.
⚠️ If the user declined disablement, warn again and obtain explicit approval immediately before deployment because non-HTTP functions may begin processing or running schedules as soon as deployment completes.
After successful deployment, inform the user:
Code deployed! Next steps to consider:
- The original app is still running — keep it as rollback for a few days
- If target-generated access keys were selected, update key-dependent clients and workflows before directing them to the new URL
- Enable HTTPS-only and managed identity on the new app for better security
- Source deletion is available only after all applicable production traffic and triggers are cut over and validated
az functionapp show --query defaultHostName -o tsv, then hit that URL and confirm it returns a non-error response (HTTP 2xx/4xx, not connection refused or 503). If an intentional access restriction returns 403 Ip Forbidden, verify deployment and function synchronization through ARM and record functional smoke testing as deferred until it can run from an already allowed client; do not relax access rules automatically.az functionapp show --query sku)curl https://<DEFAULT_HOST>/api/<FUNCTION_NAME>)production cutover complete, no production-readiness work remains deferred, and the source no longer processes production workloadsask_user as specified in automation.md — Step 7✅ Recommended safety net: When the user approves Step 4j, non-HTTP functions are disabled before deployment. Phase 6 then uses isolated target resources or a source-first, pre-approved production transaction so the target is never enabled while source-disable approval is pending. If the user declines Step 4j, record that dual processing or duplicate schedules may begin immediately after deployment. Apply the relevant mitigations below before enabling or deploying each function.
| Trigger Type | Risk | Mitigation |
|---|---|---|
| Azure Blob storage | High | Create separate container for event-based trigger in new app |
| Azure Cosmos DB | High | Create dedicated lease container for new app; set StartFromBeginning: false |
| Azure Event Grid | Medium | Recreate event subscriptions; ensure idempotent functions |
| Azure Event Hubs | Medium | Create new consumer group for new app |
| Azure Service Bus | High | Create new topic/queue; update senders; drain original before shutdown |
| Azure Storage Queue | High | Create new queue; update senders; drain original before shutdown |
| HTTP | Low | Update clients to target new app URL |
| Timer | Low | Offset schedules during cutover to avoid simultaneous execution |
| Property | Consumption | Flex Consumption |
|---|---|---|
| SKU | Y1 (Dynamic) | FC1 (FlexConsumption) |
| Plan required | Optional (auto-created) | Required (must be explicit) |
| OS | Windows | Linux |
| Configuration | App settings | functionAppConfig section |
| Storage | WEBSITE_CONTENTSHARE setting | deployment.storage in functionAppConfig |
If the source app is managed through Bicep, ARM, or Terraform:
az deployment group what-if or terraform plan before applying them.Do not mix ongoing manual configuration with resource-based deployments. If the app is not managed through IaC, skip this section.
These app settings must be filtered out before applying to the new Flex app (Step 4c). The skill handles this automatically — Step 4c streams source settings through jq, deleting these keys in memory before PATCHing the new app’s ARM endpoint.
Every Windows Consumption app has these because the platform requires them for the Azure Files SMB share. Flex uses blob-based deployment instead — these have no equivalent.
These platform content settings are distinct from explicit Azure Files mount metadata returned by az webapp config storage-account list. Windows Consumption doesn’t support explicit storage mounts, so catalog any returned metadata but don’t migrate it.
WEBSITE_CONTENTAZUREFILECONNECTIONSTRINGWEBSITE_CONTENTSHAREWEBSITE_CONTENTOVERVNETWEBSITE_SKIP_CONTENTSHARE_VALIDATIONWindows Consumption has three historical aliases for run-from-package — all must be removed:
WEBSITE_RUN_FROM_PACKAGEWEBSITE_RUN_FROM_ZIP (legacy alias — same semantics as WEBSITE_RUN_FROM_PACKAGE)WEBSITE_USE_ZIP (original name — same semantics)FUNCTIONS_EXTENSION_VERSIONFUNCTIONS_WORKER_RUNTIMEFUNCTIONS_WORKER_RUNTIME_VERSIONFUNCTIONS_MAX_HTTP_CONCURRENCYFUNCTIONS_WORKER_PROCESS_COUNTFUNCTIONS_WORKER_DYNAMIC_CONCURRENCY_ENABLEDWEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUTWEBSITE_USE_PLACEHOLDER_DOTNETISOLATEDWEBSITE_LOAD_CERTIFICATES (unused in Flex; use the site-scoped certificate process and make certificates accessible to app code)AzureWebJobsDashboard (legacy v1 setting — not used by the v4 runtime)WEBSITE_MOUNT_ENABLEDENABLE_ORYX_BUILDSCM_DO_BUILD_DURING_DEPLOYMENTWEBSITE_DNS_SERVERWEBSITE_NODE_DEFAULT_VERSIONWEBSITE_VNET_ROUTE_ALLAPPLICATIONINSIGHTS_CONNECTION_STRING — Step 4c preserves the target-specific value normally created by az functionapp create; Step 4k verifies it without displaying the value. APPLICATIONINSIGHTS_AUTHENTICATION_STRING=Authorization=AAD is preserved only when the source already used AAD ingestion.Every setting whose name starts with AzureWebJobsStorage is dropped by the 4c filter. Preserve the target binding verified by Step 4b or configured by Step 4b.opt:
AzureWebJobsStorage — discard the source connection string. Step 4b creates a fresh target connection string only when Shared Key authentication is permitted; identity-first targets must not receive one.AzureWebJobsStorage__* variants — discard source settings so they can’t silently point the target runtime at the wrong account. Preserve verified target identity settings or re-derive them through 4b.opt where conversion is permitted.