Repository: hashicorp/terraform-provider-azurerm
Pull request #29023: `azurerm_function_app_flex_consumption` - add `always_ready`
Author: login: xiaxyi
Labels: name: enhancement
name: documentation
name: size/XL
name: service/app-service
Created: 2025-03-11T06:48:31Z | Merged: 2025-05-22T10:24:41Z

<!--  All Submissions -->


## Community Note
<!-- Please leave the community note as is. -->
* Please vote on this PR by adding a :thumbsup: [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original PR to help the community and maintainers prioritize for review
* Please do not leave comments along the lines of "+1", "me too" or "any updates", they generate extra noise for PR followers and do not help prioritize for review


## Description

<!-- Please include a description below with the reason for the PR, what it is doing, what it is trying to accomplish, and anything relevant for a reviewer to know. 

If this is a breaking change for users please detail how it cannot be avoided and why it should be made in a minor version of the provider -->


## PR Checklist

- [x] I have followed the guidelines in our [Contributing Documentation](../blob/main/contributing/README.md).
- [x] I have checked to ensure there aren't other open [Pull Requests](../pulls) for the same update/change.
- [x] I have checked if my changes close any open issues. If so please include appropriate [closing keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) below.
- [x] I have updated/added Documentation as required written in a helpful and kind way to assist users that may be unfamiliar with the resource / data source.
- [x] I have used a meaningful PR title to help maintainers and other users understand this change and help prevent duplicate work. 
For example: “`resource_name_here` - description of change e.g. adding property `new_property_name_here`”


<!-- You can erase any parts of this template below this point that are not applicable to your Pull Request. -->


## Changes to existing Resource / Data Source

- [x] I have added an explanation of what my changes do and why I'd like you to include them (This may be covered by linking to an issue above, but may benefit from additional explanation).
- [x] I have written new tests for my resource or datasource changes & updated any relevant documentation.
- [x] I have successfully run tests with my changes locally. If not, please provide details on testing challenges that prevented you running the tests.
- [ ] (For changes that include a **state migration only**). I have manually tested the migration path between relevant versions of the provider.


## Testing 

- [ ] My submission includes Test coverage as described in the [Contribution Guide](../blob/main/contributing/topics/guide-new-resource.md) and the tests pass. (if this is not possible for any reason, please include details of why you did or could not add test coverage)

<!-- Please include testing logs or evidence here or an explanation on why no testing evidence can be provided. 

For state migrations please test the changes locally and provide details here, such as the versions involved in testing the migration path. For further details on testing state migration changes please see our guide on [state migrations](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/contributing/topics/guide-state-migrations.md#testing) in the contributor documentation. -->
![image](https://github.com/user-attachments/assets/acacc945-3db4-4390-a2b5-ee6f78558f74)


## Change Log

Below please provide what should go into the changelog (if anything) conforming to the [Changelog Format documented here](../blob/main/contributing/topics/maintainer-changelog.md).

<!-- Replace the changelog example below with your entry. One resource per line. -->

* `azurerm_resource` - support for the `thing1` property [GH-00000]


<!-- What type of PR is this? -->
This is a (please select all that apply):

- [ ] Bug Fix
- [ ] New Feature (ie adding a service, resource, or data source)
- [x] Enhancement
- [ ] Breaking Change


## Related Issue(s)
Fixes #0000


> [!NOTE] 
> If this PR changes meaningfully during the course of review please update the title and description as required.


Linked issue #0: 

Diff:
diff --git a/internal/services/appservice/function_app_flex_consumption_resource.go b/internal/services/appservice/function_app_flex_consumption_resource.go
index ea7d7564a040..9fec441b0807 100644
--- a/internal/services/appservice/function_app_flex_consumption_resource.go
+++ b/internal/services/appservice/function_app_flex_consumption_resource.go
@@ -23,6 +23,7 @@ import (
 	"github.com/hashicorp/terraform-provider-azurerm/internal/services/appservice/validate"
 	"github.com/hashicorp/terraform-provider-azurerm/internal/tags"
 	"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
+	"github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress"
 	"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
 	"github.com/jackofallops/kermit/sdk/web/2022-09-01/web"
 )
@@ -62,6 +63,7 @@ type FunctionAppFlexConsumptionModel struct {
 	RuntimeVersion                string                                         `tfschema:"runtime_version"`
 	MaximumInstanceCount          int64                                          `tfschema:"maximum_instance_count"`
 	InstanceMemoryInMB            int64                                          `tfschema:"instance_memory_in_mb"`
+	AlwaysReady                   []FunctionAppAlwaysReady                       `tfschema:"always_ready"`
 	SiteConfig                    []helpers.SiteConfigFunctionAppFlexConsumption `tfschema:"site_config"`
 	Identity                      []identity.ModelSystemAssignedUserAssigned     `tfschema:"identity"`
 	Tags                          map[string]string                              `tfschema:"tags"`
@@ -78,6 +80,11 @@ type FunctionAppFlexConsumptionModel struct {
 	SiteCredentials []helpers.SiteCredential `tfschema:"site_credential"`
 }
 
+type FunctionAppAlwaysReady struct {
+	Name          string `tfschema:"name"`
+	InstanceCount int64  `tfschema:"instance_count"`
+}
+
 var _ sdk.ResourceWithUpdate = FunctionAppFlexConsumptionResource{}
 
 func (r FunctionAppFlexConsumptionResource) ModelObject() interface{} {
@@ -183,6 +190,28 @@ func (r FunctionAppFlexConsumptionResource) Arguments() map[string]*pluginsdk.Sc
 			ValidateFunc: validation.IntBetween(40, 1000),
 		},
 
+		// the name is always being lower-cased by the api: https://github.com/Azure/azure-rest-api-specs/issues/33095
+		"always_ready": {
+			Type:     pluginsdk.TypeList,
+			Optional: true,
+			Elem: &pluginsdk.Resource{
+				Schema: map[string]*pluginsdk.Schema{
+					"name": {
+						Type:             pluginsdk.TypeString,
+						Required:         true,
+						ValidateFunc:     validation.StringIsNotEmpty,
+						DiffSuppressFunc: suppress.CaseDifference,
+					},
+
+					"instance_count": {
+						Type:         pluginsdk.TypeInt,
+						Optional:     true,
+						ValidateFunc: validation.IntBetween(0, 1000),
+					},
+				},
+			},
+		},
+
 		"site_config": helpers.SiteConfigSchemaFunctionAppFlexConsumption(),
 
 		"sticky_settings": helpers.StickySettingsSchema(),
@@ -432,7 +461,13 @@ func (r FunctionAppFlexConsumptionResource) Create() sdk.ResourceFunc {
 				Version: &functionAppFlexConsumption.RuntimeVersion,
 			}
 
+			alwaysReady, err := ExpandAlwaysReadyConfiguration(functionAppFlexConsumption.AlwaysReady, functionAppFlexConsumption.MaximumInstanceCount)
+			if err != nil {
+				return fmt.Errorf("expanding `always_ready` for %s: %+v", id, err)
+			}
+
 			scaleAndConcurrencyConfig := webapps.FunctionsScaleAndConcurrency{
+				AlwaysReady:          alwaysReady,
 				InstanceMemoryMB:     &functionAppFlexConsumption.InstanceMemoryInMB,
 				MaximumInstanceCount: &functionAppFlexConsumption.MaximumInstanceCount,
 			}
@@ -675,6 +710,7 @@ func (r FunctionAppFlexConsumptionResource) Read() sdk.ResourceFunc {
 					}
 
 					if faConfigScale := functionAppConfig.ScaleAndConcurrency; faConfigScale != nil {
+						state.AlwaysReady = FlattenAlwaysReadyConfiguration(faConfigScale.AlwaysReady)
 						state.InstanceMemoryInMB = pointer.From(faConfigScale.InstanceMemoryMB)
 						state.MaximumInstanceCount = pointer.From(faConfigScale.MaximumInstanceCount)
 					}
@@ -850,6 +886,14 @@ func (r FunctionAppFlexConsumptionResource) Update() sdk.ResourceFunc {
 				model.Properties.SiteConfig = siteConfig
 			}
 
+			if metadata.ResourceData.HasChange("always_ready") {
+				arc, err := ExpandAlwaysReadyConfiguration(state.AlwaysReady, state.MaximumInstanceCount)
+				if err != nil {
+					return fmt.Errorf("expanding `always_ready` for %s: %+v", id, err)
+				}
+				model.Properties.FunctionAppConfig.ScaleAndConcurrency.AlwaysReady = arc
+			}
+
 			if metadata.ResourceData.HasChange("runtime_name") {
 				runtimeName := webapps.RuntimeName(state.RuntimeName)
 				model.Properties.FunctionAppConfig.Runtime.Name = pointer.To(runtimeName)
@@ -1002,3 +1046,41 @@ func (m *FunctionAppFlexConsumptionModel) unpackFunctionAppFlexConsumptionSettin
 	}
 	m.AppSettings = appSettings
 }
+
+func ExpandAlwaysReadyConfiguration(input []FunctionAppAlwaysReady, maximumInstanceCount int64) (*[]webapps.FunctionsAlwaysReadyConfig, error) {
+	if len(input) == 0 {
+		return nil, nil
+	}
+	var totalInstanceCount int64
+	arList := make([]webapps.FunctionsAlwaysReadyConfig, 0)
+	for _, v := range input {
+		totalInstanceCount += v.InstanceCount
+		arList = append(arList, webapps.FunctionsAlwaysReadyConfig{
+			Name:          pointer.To(v.Name),
+			InstanceCount: pointer.To(v.InstanceCount),
+		})
+	}
+
+	if totalInstanceCount > maximumInstanceCount {
+		return nil, fmt.Errorf("the total number of always-ready instances should not exceed the maximum scale out limit")
+	}
+
+	return &arList, nil
+}
+
+func FlattenAlwaysReadyConfiguration(alwaysReady *[]webapps.FunctionsAlwaysReadyConfig) []FunctionAppAlwaysReady {
+	if alwaysReady == nil || len(*alwaysReady) == 0 {
+		return []FunctionAppAlwaysReady{}
+	}
+
+	alwaysReadyList := make([]FunctionAppAlwaysReady, 0)
+
+	for _, v := range *alwaysReady {
+		alwaysReadyList = append(alwaysReadyList, FunctionAppAlwaysReady{
+			Name:          pointer.From(v.Name),
+			InstanceCount: pointer.From(v.InstanceCount),
+		})
+	}
+
+	return alwaysReadyList
+}
diff --git a/internal/services/appservice/function_app_flex_consumption_resource_test.go b/internal/services/appservice/function_app_flex_consumption_resource_test.go
index 018e57f96820..abc2872a2bd3 100644
--- a/internal/services/appservice/function_app_flex_consumption_resource_test.go
+++ b/internal/services/appservice/function_app_flex_consumption_resource_test.go
@@ -6,6 +6,7 @@ package appservice_test
 import (
 	"context"
 	"fmt"
+	"regexp"
 	"testing"
 
 	"github.com/hashicorp/go-azure-helpers/lang/pointer"
@@ -194,6 +195,82 @@ func TestAccFunctionAppFlexConsumption_runtimeNode(t *testing.T) {
 	})
 }
 
+func TestAccFunctionAppFlexConsumption_alwaysReadyUpdateName(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config: r.basic(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+		{
+			Config: r.alwaysReadyBasic(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+		{
+			Config: r.alwaysReadyInstanceCount(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+		{
+			Config: r.basic(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+	})
+}
+
+func TestAccFunctionAppFlexConsumption_alwaysReadyInstanceCountError(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config:      r.alwaysReadyInstanceCountError(data),
+			ExpectError: regexp.MustCompile("the total number of always-ready instances should not exceed the maximum scale out limit"),
+		},
+	})
+}
+
+func TestAccFunctionAppFlexConsumption_alwaysReadyUpdate(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config: r.alwaysReadyInstanceCount(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+		{
+			Config: r.alwaysReadyInstanceCountUpdate(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+	})
+}
+
 func TestAccFunctionAppFlexConsumption_runtimeJava(t *testing.T) {
 	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
 	r := FunctionAppFlexConsumptionResource{}
@@ -352,7 +429,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -363,7 +440,7 @@ resource "azurerm_function_app_flex_consumption" "test" {
   storage_access_key          = azurerm_storage_account.test.primary_access_key
   runtime_name                = "node"
   runtime_version             = "20"
-  maximum_instance_count      = 50
+  maximum_instance_count      = 100
   instance_memory_in_mb       = 2048
 
   site_config {}
@@ -380,7 +457,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -414,7 +491,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -471,7 +548,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -511,7 +588,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -623,7 +700,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -655,7 +732,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -689,7 +766,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_function_app_flex_consumption" "test" {
-  name                = "acctest-LFA-tf%d"
+  name                = "acctest-LFA-%d"
   location            = azurerm_resource_group.test.location
   resource_group_name = azurerm_resource_group.test.name
   service_plan_id     = azurerm_service_plan.test.id
@@ -858,7 +935,7 @@ provider "azurerm" {
 
 %s
 resource "azurerm_user_assigned_identity" "test1" {
-  name                = "acct-uai1-%[2]d"
+  name                = "acctest-uai1-%[2]d"
   resource_group_name = azurerm_resource_group.test.name
   location            = azurerm_resource_group.test.location
 }
@@ -892,7 +969,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_user_assigned_identity" "test2" {
-  name                = "acct-uai2-%[2]d"
+  name                = "acctest-uai2-%[2]d"
   resource_group_name = azurerm_resource_group.test.name
   location            = azurerm_resource_group.test.location
 }
@@ -926,7 +1003,7 @@ provider "azurerm" {
 %s
 
 resource "azurerm_user_assigned_identity" "test2" {
-  name                = "acct-uai2-%[2]d"
+  name                = "acctest-uai2-%[2]d"
   resource_group_name = azurerm_resource_group.test.name
   location            = azurerm_resource_group.test.location
 }
@@ -951,6 +1028,175 @@ resource "azurerm_function_app_flex_consumption" "test" {
 `, r.template(data), data.RandomInteger, nodeVersion)
 }
 
+func (r FunctionAppFlexConsumptionResource) alwaysReadyBasic(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acctest-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 100
+  instance_memory_in_mb             = 2048
+  always_ready {
+    name           = "function:myHelloWorldFunction"
+    instance_count = 20
+  }
+
+  site_config {
+    application_insights_key               = azurerm_application_insights.test.instrumentation_key
+    application_insights_connection_string = azurerm_application_insights.test.connection_string
+  }
+}
+`, r.template(data), data.RandomInteger)
+}
+
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCount(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acctest-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 100
+  instance_memory_in_mb             = 2048
+  always_ready {
+    name           = "blob"
+    instance_count = 20
+  }
+
+  site_config {
+    application_insights_key               = azurerm_application_insights.test.instrumentation_key
+    application_insights_connection_string = azurerm_application_insights.test.connection_string
+  }
+}
+`, r.template(data), data.RandomInteger)
+}
+
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCountError(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acctest-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 50
+  instance_memory_in_mb             = 2048
+  always_ready {
+    name           = "blob"
+    instance_count = 20
+  }
+  always_ready {
+    name           = "function:myHelloWorldFunction"
+    instance_count = 50
+  }
+
+  site_config {}
+}
+`, r.template(data), data.RandomInteger)
+}
+
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCountUpdate(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acctest-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 100
+  instance_memory_in_mb             = 2048
+  always_ready {
+    name           = "function:myHelloWorldFunction"
+    instance_count = 20
+  }
+  always_ready {
+    name           = "blob"
+    instance_count = 20
+  }
+
+  site_config {
+    application_insights_key               = azurerm_application_insights.test.instrumentation_key
+    application_insights_connection_string = azurerm_application_insights.test.connection_string
+  }
+}
+`, r.template(data), data.RandomInteger)
+}
+
 func (FunctionAppFlexConsumptionResource) template(data acceptance.TestData) string {
 	return fmt.Sprintf(`
 resource "azurerm_resource_group" "test" {
diff --git a/website/docs/r/function_app_flex_consumption.html.markdown b/website/docs/r/function_app_flex_consumption.html.markdown
index fd72e8b7c64b..4a7ae729736f 100644
--- a/website/docs/r/function_app_flex_consumption.html.markdown
+++ b/website/docs/r/function_app_flex_consumption.html.markdown
@@ -127,6 +127,8 @@ The following arguments are supported:
 
 ~> **Note:** The `storage_user_assigned_identity_id` must be specified when `storage_authentication_type` is set to `UserAssignedIdentity`.
 
+* `always_ready` - (Optional) One or more `always_ready` blocks as defined below.
+
 * `maximum_instance_count` - (Optional) The number of workers this function app can scale out to.
 
 * `instance_memory_in_mb` - (Optional) The memory size of the instances on which your app runs. The [currently supported values](https://learn.microsoft.com/en-us/azure/azure-functions/flex-consumption-plan#instance-memory) are `2048` or `4096`.
@@ -149,6 +151,14 @@ The following arguments are supported:
 
 ---
 
+An `always_ready` block supports the following:
+
+* `name`  - (Required) The name of the `always_ready` of the Function App.
+
+* `instance_count` - (Required) The instance count of the `always_ready` of the  Function App. The minimum number is `0`. The total number of `instance_count` should not exceed the `maximum_instance_count`.
+
+---
+
 An `active_directory` block supports the following:
 
 * `client_id` - (Required) The ID of the Client to use to authenticate with Azure Active Directory.


Reviews:
user: login: catriona-m
body: Thanks for your work on this @xiaxyi - I left a couple of comments inline for you to consider but once those are addressed we can take another look, 
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-09T15:12:45Z
user: login: catriona-m
body: Thanks @xiaxyi - on having another pass through this I just spotted one more thing that could be fixed up, but otherwise this is looking good. Thanks!
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-21T13:27:00Z
user: login: catriona-m
body: Thanks @xiaxyi LGTM!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-22T10:24:13Z

Review comments:
diff_hunk: @@ -62,6 +63,7 @@ type FunctionAppFlexConsumptionModel struct {
 	RuntimeVersion                string                                         `tfschema:"runtime_version"`
 	MaximumInstanceCount          int64                                          `tfschema:"maximum_instance_count"`
 	InstanceMemoryInMB            int64                                          `tfschema:"instance_memory_in_mb"`
+	AlwaysReadyConfig             []FunctionAppAlwaysReadyConfig                 `tfschema:"always_ready_config"`
path: internal/services/appservice/function_app_flex_consumption_resource.go
user: login: catriona-m
body: could we rename this to `always_ready` since adding config at the end is redundant here?

```suggestion
	AlwaysReady            []FunctionAppAlwaysReadyConfig                 `tfschema:"always_ready"`
```
created_at: 2025-05-09T14:56:19Z
author_association: MEMBER
diff_hunk: @@ -1002,3 +1046,41 @@ func (m *FunctionAppFlexConsumptionModel) unpackFunctionAppFlexConsumptionSettin
 	}
 	m.AppSettings = appSettings
 }
+
+func ExpandAlwaysReadyConfiguration(input []FunctionAppAlwaysReadyConfig, maximumInstanceCount int64) (*[]webapps.FunctionsAlwaysReadyConfig, error) {
+	if len(input) == 0 {
+		return nil, nil
+	}
+	var totalInstanceCount int64
+	arList := make([]webapps.FunctionsAlwaysReadyConfig, 0)
+	for _, v := range input {
+		totalInstanceCount += v.InstanceCount
+		arList = append(arList, webapps.FunctionsAlwaysReadyConfig{
+			Name:          pointer.To(v.Name),
+			InstanceCount: pointer.To(v.InstanceCount),
+		})
+	}
+
+	if totalInstanceCount > maximumInstanceCount {
+		return nil, fmt.Errorf("the total of always-ready instances should not exceed the maximum sacle out limit")
path: internal/services/appservice/function_app_flex_consumption_resource.go
user: login: catriona-m
body: ```suggestion
		return nil, fmt.Errorf("the total number of always-ready instances should not exceed the maximum scale out limit")
```
created_at: 2025-05-09T14:58:41Z
author_association: MEMBER
diff_hunk: @@ -951,6 +1004,144 @@ resource "azurerm_function_app_flex_consumption" "test" {
 `, r.template(data), data.RandomInteger, nodeVersion)
 }
 
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCount(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acct-uai2-%[2]d"
path: internal/services/appservice/function_app_flex_consumption_resource_test.go
user: login: catriona-m
body: ```suggestion
  name                = "acctest-uai2-%[2]d"
```
created_at: 2025-05-09T15:00:04Z
author_association: MEMBER
diff_hunk: @@ -951,6 +1004,144 @@ resource "azurerm_function_app_flex_consumption" "test" {
 `, r.template(data), data.RandomInteger, nodeVersion)
 }
 
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCount(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acct-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 100
+  instance_memory_in_mb             = 2048
+  always_ready_config {
+    name           = "blob"
+    instance_count = 20
+  }
+
+  site_config {
+    application_insights_key               = azurerm_application_insights.test.instrumentation_key
+    application_insights_connection_string = azurerm_application_insights.test.connection_string
+  }
+
+  lifecycle {
+    ignore_changes = [webdeploy_publish_basic_authentication_enabled]
+  }
+}
+`, r.template(data), data.RandomInteger)
+}
+
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCountError(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acct-uai2-%[2]d"
path: internal/services/appservice/function_app_flex_consumption_resource_test.go
user: login: catriona-m
body: ```suggestion
  name                = "acctest-uai2-%[2]d"
```
created_at: 2025-05-09T15:00:28Z
author_association: MEMBER
diff_hunk: @@ -951,6 +1004,144 @@ resource "azurerm_function_app_flex_consumption" "test" {
 `, r.template(data), data.RandomInteger, nodeVersion)
 }
 
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCount(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acct-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 100
+  instance_memory_in_mb             = 2048
+  always_ready_config {
+    name           = "blob"
+    instance_count = 20
+  }
+
+  site_config {
+    application_insights_key               = azurerm_application_insights.test.instrumentation_key
+    application_insights_connection_string = azurerm_application_insights.test.connection_string
+  }
+
+  lifecycle {
+    ignore_changes = [webdeploy_publish_basic_authentication_enabled]
+  }
+}
+`, r.template(data), data.RandomInteger)
+}
+
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCountError(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acct-uai2-%[2]d"
+  resource_group_name = azurerm_resource_group.test.name
+  location            = azurerm_resource_group.test.location
+}
+
+resource "azurerm_function_app_flex_consumption" "test" {
+  name                = "acctest-LFA-%[2]d"
+  location            = azurerm_resource_group.test.location
+  resource_group_name = azurerm_resource_group.test.name
+  service_plan_id     = azurerm_service_plan.test.id
+
+  storage_container_type            = "blobContainer"
+  storage_container_endpoint        = azurerm_storage_container.test.id
+  storage_authentication_type       = "UserAssignedIdentity"
+  storage_user_assigned_identity_id = azurerm_user_assigned_identity.test2.id
+  runtime_name                      = "node"
+  runtime_version                   = "20"
+  maximum_instance_count            = 50
+  instance_memory_in_mb             = 2048
+  always_ready_config {
+    name           = "blob"
+    instance_count = 20
+  }
+  always_ready_config {
+    name           = "function:myHelloWorldFunction"
+    instance_count = 50
+  }
+
+  site_config {}
+  lifecycle {
+    ignore_changes = [webdeploy_publish_basic_authentication_enabled]
+  }
+}
+`, r.template(data), data.RandomInteger)
+}
+
+func (r FunctionAppFlexConsumptionResource) alwaysReadyInstanceCountUpdate(data acceptance.TestData) string {
+	return fmt.Sprintf(`
+provider "azurerm" {
+  features {}
+}
+
+%s
+
+resource "azurerm_user_assigned_identity" "test2" {
+  name                = "acct-uai2-%[2]d"
path: internal/services/appservice/function_app_flex_consumption_resource_test.go
user: login: catriona-m
body: ```suggestion
  name                = "acctest-uai2-%[2]d"
```
created_at: 2025-05-09T15:01:35Z
author_association: MEMBER
diff_hunk: @@ -194,6 +195,58 @@ func TestAccFunctionAppFlexConsumption_runtimeNode(t *testing.T) {
 	})
 }
 
+func TestAccFunctionAppFlexConsumption_alwaysReady(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config: r.alwaysReadyInstanceCount(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+	})
+}
+
+func TestAccFunctionAppFlexConsumption_alwaysReadyInstanceCountError(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config:      r.alwaysReadyInstanceCountError(data),
+			ExpectError: regexp.MustCompile("the total of always-ready instances should not exceed the maximum sacle out limit"),
+		},
+	})
+}
+
+func TestAccFunctionAppFlexConsumption_alwaysReadyUpdate(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config: r.alwaysReadyInstanceCount(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+		{
+			Config: r.alwaysReadyInstanceCountUpdate(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
path: internal/services/appservice/function_app_flex_consumption_resource_test.go
user: login: catriona-m
body: could we add more steps to test updating the `name` property and test adding and removing the block?
created_at: 2025-05-09T15:04:30Z
author_association: MEMBER
diff_hunk: @@ -194,6 +195,58 @@ func TestAccFunctionAppFlexConsumption_runtimeNode(t *testing.T) {
 	})
 }
 
+func TestAccFunctionAppFlexConsumption_alwaysReady(t *testing.T) {
+	data := acceptance.BuildTestData(t, "azurerm_function_app_flex_consumption", "test")
+	r := FunctionAppFlexConsumptionResource{}
+
+	data.ResourceTest(t, r, []acceptance.TestStep{
+		{
+			Config: r.alwaysReadyInstanceCount(data),
+			Check: acceptance.ComposeTestCheckFunc(
+				check.That(data.ResourceName).ExistsInAzure(r),
+				check.That(data.ResourceName).Key("kind").HasValue("functionapp,linux"),
+			),
+		},
+		data.ImportStep("site_credential.0.password"),
+	})
+}
path: internal/services/appservice/function_app_flex_consumption_resource_test.go
user: login: catriona-m
body: we can omit this test since this is covered in the first step of `TestAccFunctionAppFlexConsumption_alwaysReadyUpdate`
created_at: 2025-05-09T15:05:07Z
author_association: MEMBER
diff_hunk: @@ -127,6 +127,8 @@ The following arguments are supported:
 
 ~> **Note:** The `storage_user_assigned_identity_id` must be specified when `storage_authentication_type` is set to `UserAssignedIdentity`.
 
+* `always_ready_config` - (Optional) A list of `always_ready_config` of the Linux Function App. Each `always_ready_config` block supports fields documented below.
path: website/docs/r/function_app_flex_consumption.html.markdown
user: login: catriona-m
body: ```suggestion
* `always_ready` - (Optional) One or more `always_ready` blocks as defined below.
```
created_at: 2025-05-09T15:06:31Z
author_association: MEMBER
diff_hunk: @@ -149,6 +151,14 @@ The following arguments are supported:
 
 ---
 
+An `always_ready_config` block supports the following:
+
+* `name` - (Required) The name of the `always_ready_config` of the flex function app.
path: website/docs/r/function_app_flex_consumption.html.markdown
user: login: catriona-m
body: ```suggestion
* `name` - (Required) The name of the `always_ready` of the Function App.
```
created_at: 2025-05-09T15:08:01Z
author_association: MEMBER
diff_hunk: @@ -149,6 +151,14 @@ The following arguments are supported:
 
 ---
 
+An `always_ready_config` block supports the following:
+
+* `name` - (Required) The name of the `always_ready_config` of the flex function app.
+
+* `instance_count` - (Required) The instance count of the `always_ready_config` of the flex function app. The minimum number is `0` and the total number of `instance_count` under `always_ready_config` should not exceed the number of `maximum_instance_count`.
path: website/docs/r/function_app_flex_consumption.html.markdown
user: login: catriona-m
body: ```suggestion
* `instance_count` - (Required) The instance count of the `always_ready` of the  Function App. The minimum number is `0`. The total number of `instance_count` should not exceed the `maximum_instance_count`.
```
created_at: 2025-05-09T15:11:20Z
author_association: MEMBER
diff_hunk: @@ -850,6 +886,14 @@ func (r FunctionAppFlexConsumptionResource) Update() sdk.ResourceFunc {
 				model.Properties.SiteConfig = siteConfig
 			}
 
+			arc, err := ExpandAlwaysReadyConfiguration(state.AlwaysReady, state.MaximumInstanceCount)
+			if err != nil {
+				return fmt.Errorf("expanding `always_ready` for %s: %+v", id, err)
+			}
+			if metadata.ResourceData.HasChange("always_ready") {
+				model.Properties.FunctionAppConfig.ScaleAndConcurrency.AlwaysReady = arc
+			}
+
path: internal/services/appservice/function_app_flex_consumption_resource.go
user: login: catriona-m
body: should we move this inside the `HasChange` statement since there is no need to expand this unless there's a change?

```suggestion
			if metadata.ResourceData.HasChange("always_ready") {
						arc, err := ExpandAlwaysReadyConfiguration(state.AlwaysReady, state.MaximumInstanceCount)
			if err != nil {
				return fmt.Errorf("expanding `always_ready` for %s: %+v", id, err)
			}
				model.Properties.FunctionAppConfig.ScaleAndConcurrency.AlwaysReady = arc
			}

```
created_at: 2025-05-21T13:24:49Z
author_association: MEMBER

PR comments:
user: login: xiaxyi
created_at: 2025-03-11T08:12:45Z
body: The failed linter is not related to the file change in this PR
author_association: COLLABORATOR
user: login: xiaxyi
created_at: 2025-05-13T11:57:40Z
body: Thanks @catriona-m , updated the PR
author_association: COLLABORATOR
user: login: xiaxyi
created_at: 2025-05-22T06:52:44Z
body: Thanks @catriona-m , I updated the PR
author_association: COLLABORATOR
user: login: vasiredp
created_at: 2025-05-23T05:14:04Z
body: looks like $http which is predefined group name is not working . Names like blob and durable are working fine .

│ Resource Group Name: "example-flex-function-app-failover-rg"
│ Site Name: "example-flex-function-appfailover"): performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with response:
│ {"Code":"BadRequest","Message":"Site.FunctionAppConfig.ScaleAndConcurrency.AlwaysReady.InvalidName is invalid.  Found an entry in the AlwaysReady section with an invalid 'name' property: '$http'.    
│ Either specify a function by pre-pending 'function:' to it (e.g. 'function:myHelloWorldFunction') or one of the pre-defined function groups:
│ '$http,blob,durable'","Target":null,"Details":[{"Message":"Site.FunctionAppConfig.ScaleAndConcurrency.AlwaysReady.InvalidName is invalid.  Found an entry in the AlwaysReady section with an invalid   
│ 'name' property: '$http'. Either specify a function by pre-pending 'function:' to it (e.g. 'function:myHelloWorldFunction') or one of the pre-defined function groups:
│ '$http,blob,durable'"},{"Code":"BadRequest"},{"ErrorEntity":{"ExtendedCode":"51021","MessageTemplate":"{0} is invalid.
│ {1}","Parameters":["Site.FunctionAppConfig.ScaleAndConcurrency.AlwaysReady.InvalidName","Found an entry in the AlwaysReady section with an invalid 'name' property: '$http'. Either specify a function 
│ by pre-pending 'function:' to it (e.g. 'function:myHelloWorldFunction') or one of the pre-defined function groups:
author_association: NONE
user: login: xiaxyi
created_at: 2025-05-23T05:58:33Z
body: @vasiredp can you share your config here so I can give it a shot. I'd like to know what value did you assigned to the `Name` property
author_association: COLLABORATOR
user: login: vasiredp
created_at: 2025-05-23T06:14:33Z
body: working : 
name = "function:myfunctionappname"
or
name = "durable"
or
name = "blob"

not working:
name = "$http"   

if you see my error message azure have pre-defined function groups  '$http,blob,durable'

Either specify a function by pre-pending 'function:' to it (e.g. 'function:myHelloWorldFunction') or one of the pre-defined function groups:│ '$http,blob,durable'
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-06-23T02:31:09Z
body: I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
author_association: CONTRIBUTOR