The Azure Functions Premium plan removes cold starts with two separate mechanisms that are constantly confused for each other. One keeps a fixed number of instances running regardless of load; the other keeps a buffer ahead of scale-out. Configuring the wrong one leaves you paying for warm capacity and still seeing a cold first request.
Two features, not one
Microsoft describes them as working together: always ready instances are preallocated and unaffected by scaling, and prewarmed instances are a buffer as the app scales out due to HTTP events. Events are routed to the always-ready instances first; as those become busy, an instance warms in the background so the next scale step does not start from nothing. The Azure Functions Premium plan documentation sets both out, and was last updated in July 2026 at the time of writing.
For a function that calls a model API, the always-ready count is the one that matters at low traffic — a function invoked a few times an hour would otherwise scale to zero between calls and pay a full start on each. The prewarmed count matters under bursts, and only in one direction: it does nothing until instances are already busy.
Creating the plan
There is one trap in the naming and it is expensive. Microsoft warns that Premium plans hosting function apps are called Elastic Premium, with SKU names beginning with E — EP1, EP2, EP3. App Service SKUs starting with P, such as P1V2, are Dedicated plans: they will not scale dynamically and may cost more.
- Create the Elastic Premium plan:
az functionapp plan create -g RG -n my-premium-plan --location westeurope --sku EP1 --is-linux. - Create or move the function app onto it with
az functionapp create ... --plan my-premium-plan. Multiple function apps can share one plan, but they must all run the same operating system. - Set the plan’s ceiling:
az functionapp plan update -g RG -n my-premium-plan --max-burst 20. The per-app scale-out limit cannot exceed this.
The instance sizes, as documented: EP1 is 1 core with 3.5 GB of memory and 11 GB of local storage, EP2 is 2 cores with 7 GB and 21 GB, and EP3 is 4 cores with 14 GB and 61 GB. For an orchestration function that awaits a model API, EP1 is usually right and the constraint is concurrency rather than memory. One memory footnote from the same page is easy to lose: a JavaScript function app is still bounded by the Node.js default heap limit regardless of the instance size, and raising it means setting the app setting languageWorkers:node:arguments to --max-old-space-size with a value in megabytes.
Setting always-ready instances
Always-ready is an app-level setting, not a plan-level one, and it is spelled differently from what the portal calls it:
az functionapp update -g RG -n my-function-app \
--set siteConfig.minimumElasticInstanceCount=2
Two consequences of it being app-level are worth having straight before you set it. First, the plan’s minimum is the maximum across the apps in it: Microsoft’s example is three apps in one plan, two asking for one instance and one asking for five, giving a plan minimum of five — and the plan is billed for five. Second, the documented maximum number of always-ready instances per app is 20.
You can also raise the plan’s own minimum above the calculated value with az functionapp plan update --min-instances, which reserves instances in advance of scale-out. The documentation is candid that scaling beyond the minimum is best-effort and can, unusually, be delayed — which is the actual argument for reserving capacity ahead of a known traffic event rather than trusting the autoscaler.
Prewarmed instances and the warmup trigger
The prewarmed count defaults to 1 and cannot be changed in the portal; it is CLI or PowerShell only:
az functionapp update -g RG -n my-function-app \
--set siteConfig.preWarmedInstanceCount=2
Microsoft’s guidance is to leave it at 1 for most scenarios, and names the exception that applies here: an app running in a custom container has a long warm-up time and may justify a larger buffer. A model-serving function packaged as a Linux container with a heavy dependency tree is that case.
The complementary tool is the warmup trigger, which runs while an instance is being prewarmed rather than on the request path. That is where the work belongs that would otherwise happen on the first real invocation: constructing the HTTP client, reading configuration, fetching a secret from Key Vault, loading a tokenizer. Without it, a prewarmed instance is a started host with an uninitialized application — technically warm, and still slow on the first request that reaches it.
What it costs and what it does not fix
Premium billing is different in kind from Consumption, not just in amount. You pay for core seconds and memory allocated across instances, with no execution charge, and Microsoft notes that every Premium plan always has at least one active, billed instance. This is a fixed monthly floor whether the function is busy or idle. Consumption bills per-execution and per-second of consumption; the comparison is not “a bit more expensive”, it is a different shape.
The other things Premium changes, worth knowing because they interact with long model calls: the default execution timeout rises from the Consumption plan’s 10 minutes to 30 minutes and can be made unbounded in host.json, subject to documented caveats — a platform upgrade can trigger a managed shutdown with a 10-minute grace period, an idle timer stops the worker after 60 minutes with no new executions, and scale-in or a slot swap can terminate an execution. “Unbounded” means no configured limit, not a guarantee.
And the honest limitation. Always-ready instances remove the platform’s contribution to first-request latency. For a function whose work is one HTTPS call to a model endpoint, that contribution was never the dominant term: time to first token from the provider is, and no amount of warm compute in your subscription changes it. Measure the split before buying warm instances to fix a latency complaint, or you will pay a monthly floor to remove a few hundred milliseconds from a multi-second request.
The related problem Premium does not touch is what happens when the model endpoint itself is slow or throttling. Failing over to a second Azure OpenAI deployment means a second endpoint URL, a second key, a second set of deployment names and a second rate-limit budget to track, and the retry logic has to distinguish a 429 worth retrying in place from one worth routing elsewhere. That is the layer a gateway exists to be — Multigrid keeps one key and one endpoint in the function and holds the routing and fallback policy outside it, which also means the policy can change without republishing the function.
Top comments (0)