Functions Hosting Plans
Compare Azure Functions Consumption, Premium, and Dedicated plans for different workloads.
Prerequisites
- Azure subscription
- Basic understanding of serverless concepts
Azure Functions Hosting Plans Compared
Azure Functions is Microsoft's serverless compute platform that lets you run event-driven code without managing infrastructure. However, “serverless” doesn't mean there are no servers; it means you don't manage them. The hosting plan you choose fundamentally affects cold start behavior, scaling limits, networking capabilities, pricing model, and available features.
Choosing the wrong hosting plan is one of the most common mistakes teams make with Azure Functions. A startup that picks the Premium plan for a low-traffic webhook wastes hundreds of dollars per month. An enterprise that picks the Consumption plan for a latency-sensitive API serving production traffic deals with cold starts that frustrate users. This guide provides the detailed comparison and decision framework you need to make the right choice.
Hosting Plan Overview
Azure Functions offers four hosting options, each with fundamentally different trade-offs around cost, performance, and capabilities:
| Feature | Consumption | Flex Consumption | Premium (EP) | Dedicated (App Service) |
|---|---|---|---|---|
| Scale to zero | Yes | Yes (configurable) | No (1+ warm instance) | No |
| Max instances | 200 | 1000 | 100 | 10-30 (plan dependent) |
| Max execution time | 10 min (default 5) | Unlimited* | Unlimited* | Unlimited* |
| Cold start | Yes (1-10 seconds) | Reduced (configurable) | No (pre-warmed) | No |
| VNet integration | No | Yes | Yes | Yes |
| Private endpoints (inbound) | No | Yes | Yes | Yes |
| Instance memory | 1.5 GB (fixed) | 2 GB or 4 GB | 3.5-14 GB (SKU dependent) | Plan dependent |
| Minimum cost | Free tier available | Pay-per-use | ~$175/mo (1x EP1) | App Service plan cost |
| Billing model | Per execution + GB-s | Per execution + GB-s | Per instance + executions | Fixed plan cost |
*Unlimited execution time requires specific host.json configuration. Timer-triggered functions on Consumption have a 10-minute maximum.
Free Consumption Grant
The Consumption plan includes a generous free monthly grant per subscription: 1 million executions and 400,000 GB-seconds of compute time. For low-traffic APIs, scheduled tasks, webhooks, and prototypes, you can run Azure Functions entirely free. This makes Consumption the best plan for experimentation and proof-of-concept development.
Consumption Plan: True Serverless
The Consumption plan is the original serverless offering and remains the best choice for workloads with sporadic, unpredictable traffic patterns. Azure automatically allocates compute resources when your function is triggered, scales out based on demand, and bills only for actual execution time. When no functions are executing, you pay nothing.
Cold Start Deep Dive
Cold starts are the most discussed limitation of the Consumption plan. When a function hasn't been invoked recently, Azure needs to allocate a worker, load the runtime, restore dependencies, and initialize your code. This process adds latency to the first invocation.
| Language | Typical Cold Start | Factors That Increase Cold Start |
|---|---|---|
| Node.js | 1-3 seconds | Large node_modules, many dependencies |
| Python | 1-5 seconds | Large packages (pandas, numpy), virtual environments |
| .NET (in-process) | 2-5 seconds | Large assemblies, startup initialization |
| .NET (isolated) | 3-7 seconds | Additional process startup overhead |
| Java | 5-15 seconds | JVM startup, Spring Boot initialization, classpath scanning |
| PowerShell | 3-10 seconds | Module imports, profile loading |
Minimizing Cold Starts on Consumption
While cold starts cannot be eliminated on Consumption, several strategies can reduce them:
- Minimize dependencies: Every package your function loads adds to cold start time. Remove unused dependencies and prefer lightweight libraries.
- Use the latest runtime version: Microsoft continuously improves cold start performance in newer runtime versions. Always target the latest Functions runtime.
- Lazy initialization: Defer heavy initialization (database connections, client creation) to the first actual invocation rather than module load time.
- Keep functions warm with a timer: A timer-triggered function that runs every 5 minutes keeps the instance allocated. However, this adds cost and is essentially a hack; consider Flex Consumption or Premium if you need consistent warm starts.
{
"version": "2.0",
"functionTimeout": "00:10:00",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"maxTelemetryItemsPerSecond": 20,
"excludedTypes": "Request;Dependency"
}
},
"logLevel": {
"default": "Warning",
"Host.Results": "Information",
"Function": "Information"
}
},
"extensions": {
"http": {
"routePrefix": "api",
"maxOutstandingRequests": 200,
"maxConcurrentRequests": 100
},
"queues": {
"maxPollingInterval": "00:00:02",
"visibilityTimeout": "00:00:30",
"batchSize": 16,
"maxDequeueCount": 5,
"newBatchThreshold": 8
}
}
}Consumption Plan Limitations
Beyond cold starts, the Consumption plan has several hard limitations: 1.5 GB memory per instance (not configurable), no VNet integration (cannot access private endpoints or resources behind firewalls), 10-minute maximum execution time, and a 200-instance scaling limit. If any of these are blockers, Flex Consumption or Premium is required.
Flex Consumption Plan: The Best of Both Worlds
Flex Consumption is the newest hosting option and represents a significant evolution of the serverless model. It addresses nearly every limitation of the original Consumption plan while retaining pay-per-use pricing. For most new serverless projects, Flex Consumption should be the default choice.
Key Advantages Over Standard Consumption
- VNet integration: Full virtual network support for accessing private resources, a critical requirement for enterprise workloads that standard Consumption cannot provide.
- Always-ready instances: Configure a minimum number of pre-provisioned instances to eliminate cold starts for critical functions, while still scaling to zero for non-critical ones. You only pay for always-ready instances when they are provisioned.
- Higher scale limits: Scales up to 1,000 instances compared to 200 for standard Consumption and 100 for Premium.
- Configurable instance memory: Choose between 2,048 MB and 4,096 MB instance sizes depending on workload needs.
- Private endpoint support: Inbound private endpoints are supported, enabling fully private function apps accessible only from within your VNet.
- Faster scaling: Improved concurrency management and faster instance allocation compared to standard Consumption.
# Create a Flex Consumption function app with VNet integration
az functionapp create \
--name my-flex-func \
--resource-group myRG \
--storage-account mystorageaccount \
--runtime node \
--runtime-version 20 \
--functions-version 4 \
--flexconsumption-location "East US 2" \
--instance-memory 2048
# Configure always-ready instances for the HTTP trigger group
az functionapp scale config set \
--name my-flex-func \
--resource-group myRG \
--always-ready-instances http=1
# Set maximum instance count
az functionapp scale config set \
--name my-flex-func \
--resource-group myRG \
--maximum-instance-count 100
# Enable VNet integration
az functionapp vnet-integration add \
--name my-flex-func \
--resource-group myRG \
--vnet my-vnet \
--subnet functions-subnetFlex Consumption for New Projects
For new serverless projects that need VNet integration, Flex Consumption should be your default choice. It provides pay-per-use pricing like Consumption but adds VNet support, configurable instance sizes, faster scaling, and always-ready instances, features that previously required the significantly more expensive Premium plan. The only reasons to use standard Consumption over Flex are if Flex is not yet available in your region or you need to stay within the free grant.
Premium Plan: Enterprise Serverless
The Premium plan (Elastic Premium, EP1/EP2/EP3) is designed for production workloads that need predictable performance with zero cold starts, VNet integration, and longer execution times. It maintains at least one pre-warmed instance at all times, ensuring that the first invocation is always fast.
Premium SKU Comparison
| SKU | vCPU | Memory | Approx. Monthly Cost | Best For |
|---|---|---|---|---|
| EP1 | 1 | 3.5 GB | ~$175 | Low to moderate workloads, APIs |
| EP2 | 2 | 7 GB | ~$350 | Medium workloads, memory-intensive functions |
| EP3 | 4 | 14 GB | ~$700 | High-compute workloads, ML inference |
# Create an Elastic Premium plan
az functionapp plan create \
--name my-premium-plan \
--resource-group myRG \
--location eastus2 \
--sku EP1 \
--min-instances 1 \
--max-burst 20
# Create the Function App on the Premium plan
az functionapp create \
--name my-premium-func \
--resource-group myRG \
--plan my-premium-plan \
--runtime node \
--runtime-version 20 \
--storage-account mystorageaccount \
--functions-version 4
# Enable VNet integration for accessing private resources
az functionapp vnet-integration add \
--name my-premium-func \
--resource-group myRG \
--vnet my-vnet \
--subnet functions-subnet
# Configure deployment slots for zero-downtime updates
az functionapp deployment slot create \
--name my-premium-func \
--resource-group myRG \
--slot staging
# Swap staging to production
az functionapp deployment slot swap \
--name my-premium-func \
--resource-group myRG \
--slot staging \
--target-slot productionPre-Warmed vs Minimum Instances
Premium plans have two scaling controls that are often confused:
- Minimum instances (plan level): The minimum number of instances that are always allocated and billed. Set this to at least 1 to eliminate cold starts. Each minimum instance is fully billed at the EP SKU rate.
- Pre-warmed instances (app level): Additional instances kept warm beyond the minimum, ready to handle burst traffic. These are billed at a reduced rate (~50% of a fully active instance). Set this to the number of additional instances you typically need during traffic spikes.
Premium Plan Cost Optimization
The Premium plan's cost is dominated by the minimum instance count. If you set--min-instances 3 on an EP2 plan, you pay approximately $1,050/month even with zero traffic. Set the minimum to 1 for most workloads and let Azure scale out additional instances on demand. Monitor your scaling patterns and adjust minimum instances only if you consistently need more baseline capacity.
Dedicated (App Service) Plan
Running Functions on a Dedicated App Service plan means your functions share compute with other App Service apps on the same plan. This is practical when you already have underutilized App Service plans, need App Service Environment (ASE) for full network isolation, or prefer predictable, fixed-cost billing over usage-based pricing.
When Dedicated Makes Sense
- Existing underutilized App Service plans: If you have an App Service plan running web apps at 20% utilization, adding Functions to the same plan costs nothing extra and maximizes your investment.
- Long-running functions: Dedicated plans have no execution time limit, making them suitable for functions that process for minutes or hours (video encoding, data migration, ETL pipelines).
- App Service Environment (ASE) requirements: For single-tenant, fully isolated compute environments required by compliance standards, ASEv3 with Dedicated plans provides the highest level of network isolation.
- Predictable billing: You pay for the App Service plan regardless of function execution count, making costs completely predictable for budgeting.
Avoid Free/Shared Tiers for Functions
While technically possible, running Azure Functions on Free or Shared App Service plan tiers results in significant limitations: no “Always On” setting (functions time out and stop responding), limited CPU allocation, no custom domains with SSL, and no scaling. Use at least a Basic B1 plan or higher for Dedicated function hosting. For production workloads, Premium v3 tiers offer the best price-to-performance ratio.
Triggers, Bindings, and Plan Compatibility
Azure Functions supports dozens of trigger types that connect your code to events from various Azure services and third-party systems. While most triggers work on all plans, some have plan-specific behaviors or limitations.
| Trigger Type | Consumption | Flex Consumption | Premium | Notes |
|---|---|---|---|---|
| HTTP | Full support | Full support | Full support | Cold starts affect latency on Consumption |
| Timer | Max 10 min interval | Full support | Full support | Timer must run on exactly one instance |
| Queue Storage | Full support | Full support | Full support | Batch size affects throughput |
| Service Bus | Full support | Full support | Full support | Use managed identity for auth |
| Event Hub | Full support | Full support | Full support | Max instances = number of partitions |
| Cosmos DB | Full support | Full support | Full support | Requires change feed; use lease container |
| Kafka | Not supported | Full support | Full support | Requires VNet for private Kafka clusters |
| Durable Functions | Full (with limits) | Full support | Full support | Fan-out limited by instance count |
Durable Functions and Orchestration
Durable Functions is an extension of Azure Functions that lets you write stateful workflows in code. It provides orchestration patterns like chaining, fan-out/fan-in, human interaction, and monitoring without external state stores.
const df = require("durable-functions");
// Orchestrator function - coordinates the workflow
df.app.orchestration("processOrderOrchestrator", function* (context) {
const orderId = context.df.getInput();
// Step 1: Validate the order
const validation = yield context.df.callActivity("validateOrder", orderId);
if (!validation.isValid) {
return { status: "rejected", reason: validation.reason };
}
// Step 2: Fan-out - process items in parallel
const items = validation.items;
const parallelTasks = items.map((item) =>
context.df.callActivity("processItem", { orderId, item })
);
const results = yield context.df.Task.all(parallelTasks);
// Step 3: Calculate totals after all items are processed
const total = yield context.df.callActivity("calculateTotal", results);
// Step 4: Charge payment
const payment = yield context.df.callActivity("chargePayment", {
orderId,
amount: total,
});
return { status: "completed", orderId, total, paymentId: payment.id };
});
// Activity functions - the actual work
df.app.activity("validateOrder", { handler: async (orderId) => {
// Validate against database
return { isValid: true, items: ["item1", "item2", "item3"] };
}});
df.app.activity("processItem", { handler: async ({ orderId, item }) => {
// Process each item (inventory check, reservation, etc.)
return { item, processed: true, price: 29.99 };
}});Durable Functions Task Hub
Durable Functions uses Azure Storage (queues and tables) as its backend state store by default. For high-throughput scenarios, consider using the Netherite storage provider (based on Event Hubs and Azure Page Blobs) or the MSSQL storage provider. The storage backend choice significantly affects orchestration throughput and latency. Configure the task hub name in host.json to isolate different function apps sharing the same storage account.
Monitoring and Observability
Azure Functions integrates with Application Insights for comprehensive monitoring. Proper instrumentation is critical for understanding performance, identifying failures, and optimizing costs.
# Create Application Insights
az monitor app-insights component create \
--app my-func-insights \
--resource-group myRG \
--location eastus2
# Connect Function App to Application Insights
az functionapp config appsettings set \
--name my-premium-func \
--resource-group myRG \
--settings \
APPLICATIONINSIGHTS_CONNECTION_STRING=$(az monitor app-insights component show --app my-func-insights -g myRG --query connectionString -o tsv) \
FUNCTIONS_WORKER_RUNTIME=node \
WEBSITE_RUN_FROM_PACKAGE=1
# View function execution logs
az monitor app-insights query \
--app my-func-insights \
--resource-group myRG \
--analytics-query "requests | where timestamp > ago(1h) | summarize count(), avg(duration) by name | order by count_ desc"Key Metrics to Monitor
| Metric | What It Tells You | Alert Threshold |
|---|---|---|
| Function execution count | Volume of invocations | Sudden drops may indicate trigger failure |
| Function execution duration | P50/P95/P99 latency | P95 exceeding SLO target |
| Function failures | Error rate | Error rate above 1-5% |
| Active instance count | Current scaling level | Approaching plan maximum |
| Health check status | Instance availability | Unhealthy instances detected |
Cost Comparison Scenarios
Understanding cost at different traffic levels helps you choose the most economical plan. These scenarios compare monthly costs for identical workloads across plans.
Scenario 1: Low-Traffic API (10K requests/day)
| Plan | Monthly Cost | Notes |
|---|---|---|
| Consumption | ~$0 (within free grant) | Cold starts on first request after idle |
| Flex Consumption | ~$5-15 | No cold starts if always-ready configured |
| Premium EP1 | ~$175 | Massive overkill for this traffic level |
Scenario 2: High-Traffic API (1M requests/day, 200ms avg)
| Plan | Monthly Cost | Notes |
|---|---|---|
| Consumption | ~$80-120 | May hit scaling limits during spikes |
| Flex Consumption | ~$100-150 | Better scaling, VNet support |
| Premium EP1 (min 2) | ~$350-500 | Predictable performance, no cold starts |
Execution Billing Details
Consumption and Flex Consumption plans bill based on the number of executions and the resource consumption measured in GB-seconds (memory allocated multiplied by execution duration). For example, a function using 256 MB of memory running for 1 second consumes 0.25 GB-s. The Consumption free grant of 400,000 GB-s per month covers approximately 1.6 million such executions. Monitor your actual GB-s consumption in Application Insights to predict costs accurately.
Security and Networking Best Practices
Securing Azure Functions requires attention to authentication, network isolation, and secret management.
Authentication Options
- Function keys: Built-in API keys (function-level and host-level). Simple but not recommended for production; keys are stored in the function app and can be leaked.
- Azure AD authentication (EasyAuth): Built-in authentication middleware that validates Azure AD tokens. No code changes required. Configure in the portal or via CLI.
- Custom authentication: Implement your own JWT validation in code for maximum flexibility (multiple identity providers, custom claims).
- API Management: Place Azure API Management in front of Functions for rate limiting, API versioning, subscription keys, and OAuth 2.0 validation.
# Restrict function app to VNet-only access (Premium/Flex required)
az functionapp config access-restriction add \
--name my-premium-func \
--resource-group myRG \
--rule-name "AllowVNet" \
--priority 100 \
--vnet-name my-vnet \
--subnet functions-subnet
# Enable managed identity for Key Vault access
az functionapp identity assign \
--name my-premium-func \
--resource-group myRG
# Set Key Vault references for secrets (no secrets in app settings)
az functionapp config appsettings set \
--name my-premium-func \
--resource-group myRG \
--settings \
"DB_CONNECTION=@Microsoft.KeyVault(VaultName=myapp-kv;SecretName=db-connection)" \
"API_KEY=@Microsoft.KeyVault(VaultName=myapp-kv;SecretName=external-api-key)"
# Enable Azure AD authentication
az webapp auth update \
--name my-premium-func \
--resource-group myRG \
--enabled true \
--action LoginWithAzureActiveDirectoryDecision Guide
Use this framework to select the right hosting plan for your workload:
- Is the workload sporadic with low traffic and no VNet requirement?→ Use Consumption. The free grant and scale-to-zero make it the cheapest option for lightweight workloads, prototypes, and scheduled tasks.
- Do you need VNet access with pay-per-use pricing? → UseFlex Consumption. It bridges the gap between Consumption and Premium at a fraction of the cost.
- Is latency critical with no cold starts allowed? → UsePremium with pre-warmed instances. The always-on minimum instance ensures sub-second response times for every request.
- Do you have existing App Service plans with spare capacity? → Use Dedicated. Consolidate functions onto existing plans to maximize utilization without additional cost.
- Need full network isolation (ASE)? → Use Dedicatedwith App Service Environment v3 for single-tenant, fully isolated compute.
- Running event-driven microservices with KEDA? → ConsiderAzure Container Apps as an alternative that provides Kubernetes-based scaling with built-in KEDA support.
Key Takeaways
- 1Consumption plan is pay-per-execution and scales to zero, making it best for sporadic workloads.
- 2Premium plan eliminates cold starts with pre-warmed instances and supports VNet integration.
- 3Dedicated (App Service) plan uses existing App Service infrastructure at fixed cost.
- 4Flex Consumption combines serverless scaling with always-ready instances.
- 5Consumption plan has a 5-minute default timeout (max 10); Premium supports up to 60 minutes.
- 6Choose based on latency requirements, execution duration, networking needs, and budget.
Frequently Asked Questions
What is the Azure Functions Consumption plan?
How do I avoid cold starts in Azure Functions?
When should I use the Premium plan over Consumption?
Can Azure Functions connect to resources in a VNet?
What is the maximum execution time for Azure Functions?
Written by CloudToolStack Team
Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.
Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.