Skip to content

02 - First Deploy (Premium)

Deploy a Node.js Function App to an Elastic Premium plan (EP1) with always-warm instances, then publish code and verify the app is live.

Prerequisites

  • You completed 01 - Run Locally.
  • You are signed in to Azure CLI and have Contributor access.
  • You already exported: $RG, $APP_NAME, $PLAN_NAME, $STORAGE_NAME, $LOCATION (use koreacentral for this guide).

What You'll Build

  • A Linux Node.js Function App on Elastic Premium (EP1) with runtime settings.
  • Always-warm instances for production latency requirements.
  • A first deployment pipeline (func azure functionapp publish) and endpoint verification.

Infrastructure Context

Plan: Premium (EP1) | Network: Public (VNet optional) | Always warm: ✅

Premium deploys with pre-warmed instances, Azure Files content share for deployment, and optional VNet integration. Storage uses connection string authentication by default.

flowchart TD
    INET[Internet] -->|HTTPS| FA[Function App\nPremium EP1\nLinux Node.js 20]

    subgraph PLAN["Elastic Premium Plan"]
        FA
        WARM["Pre-warmed instances\nMin: 1"]
    end

    FA --> ST["Storage Account\nAzure Files content share"]
    FA --> AI[Application Insights]
    FA -.->|System-Assigned MI| ENTRA[Microsoft Entra ID]

    style FA fill:#ff8c00,color:#fff
    style PLAN fill:#E8F5E9,stroke:#4CAF50
    style ST fill:#FFF3E0
    style WARM fill:#FFF3E0,stroke:#FF9800

Steps

  1. Set environment variables for the deployment.

    export RG="rg-func-node-prem-demo"
    export LOCATION="koreacentral"
    export STORAGE_NAME="stndprem0410"
    export PLAN_NAME="plan-ndprem-04100022"
    export APP_NAME="func-ndprem-04100022"
    

    Globally unique names required

    Both $APP_NAME and $STORAGE_NAME must be globally unique across all Azure subscriptions. If you get a naming conflict, append a random suffix (e.g., func-ndprem-04091234).

  2. Authenticate and set subscription context.

    az login
    az account set --subscription "<subscription-id>"
    
  3. Create resource group.

    az group create \
      --name "$RG" \
      --location "$LOCATION"
    

    Expected output (abridged):

    {
      "name": "rg-func-node-prem-demo",
      "location": "koreacentral",
      "properties": {
        "provisioningState": "Succeeded"
      }
    }
    
  4. Create storage account.

    az storage account create \
      --name "$STORAGE_NAME" \
      --resource-group "$RG" \
      --location "$LOCATION" \
      --sku "Standard_LRS" \
      --kind "StorageV2" \
      --allow-blob-public-access false
    

    Expected output (abridged):

    {
      "name": "<storage-account-name>",
      "location": "koreacentral",
      "kind": "StorageV2",
      "provisioningState": "Succeeded"
    }
    
  5. Create the Premium plan (EP1, Linux).

    az functionapp plan create \
      --name "$PLAN_NAME" \
      --resource-group "$RG" \
      --location "$LOCATION" \
      --sku "EP1" \
      --is-linux
    

    Expected output (abridged):

    {
      "name": "<plan-name>",
      "location": "koreacentral",
      "sku": {
        "name": "EP1",
        "tier": "ElasticPremium"
      },
      "provisioningState": "Succeeded"
    }
    
  6. Create the Function App on the Premium plan.

    az functionapp create \
      --name "$APP_NAME" \
      --resource-group "$RG" \
      --plan "$PLAN_NAME" \
      --storage-account "$STORAGE_NAME" \
      --runtime "node" \
      --runtime-version "20" \
      --functions-version "4" \
      --os-type "Linux"
    

    Node.js 20 EOL approaching

    Azure CLI warns: Use node version 24 as 20 will reach end-of-life on 2026-04-30. Consider using --runtime-version 22 or later for new projects.

    Expected output (abridged):

    {
      "name": "func-ndprem-04100022",
      "state": "Running",
      "kind": "functionapp,linux",
      "defaultHostName": "func-ndprem-04100022.azurewebsites.net"
    }
    

    Application Insights auto-created

    az functionapp create automatically creates an Application Insights resource with the same name as the function app (e.g., func-ndprem-04100022), not $APP_NAME-ai. The APPLICATIONINSIGHTS_CONNECTION_STRING app setting is auto-configured.

    Enterprise policy: Shared key access

    Some enterprise subscriptions enforce Azure Policy that sets allowSharedKeyAccess: false on all storage accounts. Premium (EP1) requires WEBSITE_CONTENTAZUREFILECONNECTIONSTRING with a connection string that uses shared key access to create the content file share during provisioning. If your subscription has this policy, the Function App creation will fail with a 403 error. Solutions:

    • Request a policy exemption from your Azure administrator
    • Use Flex Consumption (FC1) which supports identity-based blob storage without shared keys
    • Use Dedicated (B1) which uses WEBSITE_RUN_FROM_PACKAGE without a content file share
  7. Publish the app.

    cd apps/nodejs
    func azure functionapp publish "$APP_NAME"
    

    Expected output (abridged):

    Getting site publishing info...
    Uploading package...
    Uploading 49.36 MB [##############################################################]
    Upload completed successfully.
    Deployment completed successfully.
    Syncing triggers...
    

    EventHub placeholder required

    If your app includes an Event Hub trigger, the function host may fail to start without a valid EventHubConnection setting. Set a placeholder:

    az functionapp config appsettings set \
      --name "$APP_NAME" \
      --resource-group "$RG" \
      --settings "EventHubConnection__fullyQualifiedNamespace=placeholder.servicebus.windows.net"
    
  8. Validate deployment.

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

    Function indexing delay

    After the first publish, it may take 30–60 seconds for all functions to appear in the ARM API. If the list is empty, wait and retry.

    Expected output (abridged — showing key functions):

    Name                                          Language
    --------------------------------------------  ----------
    func-ndprem-04100022/helloHttp                node
    func-ndprem-04100022/health                   node
    func-ndprem-04100022/info                     node
    func-ndprem-04100022/queueProcessor           node
    func-ndprem-04100022/blobProcessor            node
    func-ndprem-04100022/scheduledCleanup         node
    

    Language field

    The Language column shows node, not Javascript. This is the actual value returned by the ARM API for Node.js v4 apps.

  9. Test the deployed endpoints.

    curl --request GET "https://$APP_NAME.azurewebsites.net/api/health"
    

    Expected output:

    {"status":"healthy","timestamp":"2026-04-09T15:42:13.827Z","version":"1.0.0"}
    
    curl --request GET "https://$APP_NAME.azurewebsites.net/api/hello/Azure"
    

    Expected output:

    {"message":"Hello, Azure"}
    

Verification

The output confirms that Azure indexed your function definitions and the app serves requests. Verify:

  • az functionapp function list shows functions with language node
  • curl to the health endpoint returns 200 OK with {"status":"healthy",...}
  • curl to /api/hello/Azure returns {"message":"Hello, Azure"}

See Also

Sources