Skip to content

05 - Infrastructure as Code (Consumption)

Describe your .NET Function App platform using Bicep so provisioning is deterministic and easy to review.

Prerequisites

Tool Version Purpose
.NET SDK 8.0 (LTS) Build and run isolated worker functions
Azure Functions Core Tools v4 Start local host and publish artifacts
Azure CLI 2.61+ Provision Azure resources and inspect app state

Consumption plan basics

Consumption (Y1) is serverless with scale-to-zero, up to 200 instances, 1.5 GB memory per instance, and a default 5-minute timeout (max 10 minutes).

What You'll Build

You will define a complete Consumption environment in Bicep (storage account, Y1 plan, and Linux Function App for .NET 8 isolated worker), apply required host storage settings, and deploy from your own template.

flowchart TD
    A[Bicep template] --> B[az deployment group create]
    B --> C[Function App + Plan + Storage]
    C --> D["Build + publish from output dir"]

Steps

Step 1 - Create a Bicep template for your .NET Function App

param location string = resourceGroup().location
param baseName string

var storageName = toLower(replace('${baseName}storage', '-', ''))
var planName = '${baseName}-plan'
var appName = '${baseName}-func'
var contentShareName = toLower(replace('${baseName}-content', '-', ''))

Step 2 - Define Function App runtime settings

resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
}

resource plan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: planName
  location: location
  kind: 'linux'
  sku: {
    name: 'Y1'
    tier: 'Dynamic'
  }
  properties: {
    reserved: true
  }
}

resource functionApp 'Microsoft.Web/sites@2023-12-01' = {
  name: appName
  location: location
  kind: 'functionapp,linux'
  properties: {
    serverFarmId: plan.id
    httpsOnly: true
    siteConfig: {
      linuxFxVersion: 'DOTNET-ISOLATED|8.0'
      appSettings: [
        { name: 'FUNCTIONS_EXTENSION_VERSION'; value: '~4' }
        { name: 'FUNCTIONS_WORKER_RUNTIME'; value: 'dotnet-isolated' }
        { name: 'AzureWebJobsStorage'; value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, storage.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' }
        { name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'; value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, storage.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' }
        { name: 'WEBSITE_CONTENTSHARE'; value: contentShareName }
      ]
    }
  }
}

.NET-specific Bicep settings

  • linuxFxVersion: 'DOTNET-ISOLATED|8.0' sets the .NET 8 isolated worker runtime.
  • FUNCTIONS_WORKER_RUNTIME: 'dotnet-isolated' tells the host to use the .NET isolated worker.
  • WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE are required for Consumption plan.

Step 3 - Deploy infrastructure

az deployment group create \
  --resource-group "$RG" \
  --template-file main.bicep \
  --parameters baseName="$BASE_NAME"

Step 4 - Deploy application artifact

After infrastructure is provisioned, build and publish from the output directory:

cd apps/dotnet
dotnet publish --configuration Release --output ./publish

cd publish
func azure functionapp publish "$APP_NAME" --dotnet-isolated

Must pass --dotnet-isolated flag

When publishing from the compiled output directory, Core Tools cannot detect the project language. Always pass --dotnet-isolated to specify the worker runtime explicitly. Without this flag, the publish may succeed but functions will not be indexed correctly.

Step 5 - Validate infrastructure deployment

az deployment group show \
  --resource-group "$RG" \
  --name main \
  --query "properties.provisioningState" \
  --output tsv

az functionapp show \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --output table

Verification

Infrastructure deployment output:

ProvisioningState    Timestamp
-----------------    --------------------------
Succeeded            2026-04-09T17:00:00.000Z

Function app status:

Name                       State    ResourceGroup            DefaultHostName
-------------------------  -------  -----------------------  -------------------------------------------
func-dotnetcon-04100220    Running  rg-func-dotnet-con-demo  func-dotnetcon-04100220.azurewebsites.net

Next Steps

Next: 06 - CI/CD

See Also

Sources