
Azure FunctionsAuthorCloudBrum editorial teamLast reviewedReading time~12 minLevelBeginner to advanced
Microsoft Azure · Compute · Serverless functions (FaaS)
Event-driven code on Azure without server chores. Write a function, attach a trigger such as an HTTP call, a queue message or a timer, and Azure runs it on demand. The hosting plan you pick decides how it scales and what it costs.
On this page (17 sections)
Mind map: Azure Functions at a glance
Free to share. The downloaded image includes the CloudBrum link.
Key features (summary)
- Triggers and bindingsA trigger starts the function and bindings read or write data, so a queue-to-database job needs little glue code.
- Several hosting plansFlex Consumption, Premium and Dedicated plans, plus the older Consumption plan, trade price against start-up speed, networking and limits.
- Many languagesWrite in C#, JavaScript, TypeScript, Python, Java or PowerShell, or bring your own runtime with a custom handler.
- Scale to zero and outApps scale out as events arrive and, on serverless plans, back to zero when there is nothing to do.
- Always ready instancesOn Flex Consumption and Premium you can keep warm instances ready to cut the start-up delay.
- Durable FunctionsWrite long-running, stateful workflows in code, with fan-out, waiting for people or events, and automatic checkpoints.
- Identity-first securityManaged identities, Microsoft Entra sign-in, Key Vault references and private networking keep keys out of your code.
- Built-in monitoringApplication Insights collects logs, traces, failures and live metrics for each function.
Basic concepts
- Function app
- The deployable unit. It holds one or more functions that share a hosting plan, settings, identity and scaling.
- Function
- One piece of code with exactly one trigger. A function app can contain many of them.
- Trigger
- What starts a function: an HTTP request, a timer, a queue message, a blob upload, an event and so on.
- Binding
- A declared connection to data. An input binding reads data for the function, and an output binding writes the result somewhere.
- Hosting plan
- The compute model for the app: Flex Consumption, Premium, Dedicated (App Service) or the older Consumption plan.
- Flex Consumption
- The newer serverless plan with per-function scaling, selectable instance memory, virtual network support and optional always ready instances.
- Always ready instance
- An instance kept running so that the first request does not wait for a new one to start. It is billed for as long as it is kept ready.
- Isolated worker model
- For .NET, your code runs in its own process, separate from the Functions host. It is the model that continues to be supported and updated.
- Host storage account
- A storage account the Functions host uses for internal state, such as trigger coordination and, on some plans, the deployment package.
- Managed identity
- An identity for the function app in Microsoft Entra ID, used to reach other Azure services without stored secrets.
- Authorization level
- For HTTP triggers: anonymous, function or admin. Non-anonymous levels require an access key.
- Extension bundle
- A versioned set of binding extensions that the host loads, so non-.NET apps get triggers and bindings without extra installs.
How to create & configure it
Set up a function app in the Azure portal
- Start a new Function AppIn the Azure portal search for Function App and choose Create. Pick the subscription and a resource group.
- Choose a hosting optionFor a new serverless app, start with Flex Consumption. Choose Premium if you need constant warm capacity with full networking, or a Dedicated plan if you already run an App Service plan.
- Name it and pick the runtimeThe name must be unique across Azure, because it becomes the web address. Choose the region, the language stack and the version.
- Choose instance size and scale limitsOn Flex Consumption set the instance memory and the maximum number of instances. A cap protects downstream systems from a flood of parallel runs.
- Set up storageCreate or choose a storage account for the host. Keep it private and use identity-based access where you can.
- Decide on networkingLeave public access on for a first test, or use virtual network integration and private endpoints for production.
- Turn on monitoringEnable Application Insights so failures and slow runs show up. Plan sampling to keep log volume, and cost, under control.
- Give the app an identityEnable a system-assigned managed identity and grant it only the roles your code needs, such as a queue or table role on one storage account.
- Write and deploy the codeDevelop locally with Azure Functions Core Tools or Visual Studio Code, then deploy from the command line, a pipeline or the editor.
- Test, watch and tuneRun the function, open the Failures and Live metrics views in Application Insights, and adjust concurrency, batch size and always ready settings.
Tip: once it works by hand, describe the app, its plan and the storage account in Bicep, Terraform or the Azure CLI (see the code references); test and production then come from the same template.
Common issues after configuration
| Symptom | Likely cause | What to check / fix |
|---|---|---|
| Host will not start, or the portal says it cannot reach storage | Wrong storage setting or missing role | Check the host storage setting and, when using identity-based access, that the app’s identity has the required storage roles. Look for firewall rules on the storage account. |
| 404 Not Found on an HTTP function | Wrong route or the code is not deployed | Remember the default /api route prefix, check the function name and route, and confirm the deployment finished and the function appears in the portal. |
| 401 Unauthorized | Missing key or blocked by sign-in | Send the function key in the x-functions-key header, or check that built-in authentication is not rejecting the caller. |
| HTTP call fails after about four minutes | The platform’s HTTP limit | An HTTP-triggered function must answer within roughly 230 seconds. Return 202 Accepted, put the work on a queue and let the client poll. |
| Slow first request | The app had been idle and an instance had to start | Use always ready instances on Flex Consumption or the Premium plan, keep the package small and create clients once. |
| Messages end up in the poison queue | The function keeps throwing | Read the failures in Application Insights, fix the cause, then replay messages from the -poison queue. |
| The same message is handled twice | Queue triggers deliver at least once | Write results with an upsert keyed on the message’s unique ID, so a replay changes nothing. |
| Cannot reach a private database or service | Network or DNS setup | Check virtual network integration, the subnet, the private DNS zone and the target’s firewall. |
| Cannot create a Flex Consumption app in a Region | Regional memory quota or Region support | Pick another supported Region, or request more quota for the subscription. |
| Timer runs at an unexpected hour | Schedules use UTC by default | Write the CRON expression in UTC, or set the time-zone application setting for the app. |
| Application Insights costs more than the function | Too much logging | Turn on sampling, log at a higher level in production and set retention and a daily cap. |
| A .NET in-process app is flagged as out of support | The in-process model is ending | Migrate to the isolated worker model before support ends on 10 November 2026. |
Use cases: when and where to use it
Good fit
- Web APIs and webhooks whose traffic arrives in bursts
- Processing queue, event or file-upload messages
- Scheduled jobs and housekeeping
- Connecting Azure services and automating routine admin
- Data-prep steps and light ETL
- Long workflows with Durable Functions
Consider something else
- Servers you fully control → Azure Virtual Machines
- Full web apps and APIs with steady traffic → Azure App Service
- Containerised microservices → Azure Container Apps or AKS
- Low-code integration flows → Azure Logic Apps
- Workloads that never idle → a Premium or Dedicated plan, or containers, often costs less
Pros: why consider it?
Why teams choose it
- No operating system or host for you to patch
- Triggers and bindings remove a lot of boilerplate
- Scales to zero on serverless plans
- Choice of hosting plan for each workload
- Durable Functions for long workflows
- Tight links with Entra ID, Key Vault and Application Insights
Trade-offs to weigh
- Plans differ in limits and features, so choosing takes thought
- Cold starts on scale-to-zero plans
- Storage account and monitoring add side costs
- Local testing of triggers needs emulators or real services
- Scale-out can overwhelm downstream systems without caps
- Some patterns tie your code to Azure bindings
Common threats, vulnerabilities & risks
| Risk | Severity | Why it matters | Mitigation |
|---|---|---|---|
| Anonymous or leaked HTTP access | High | An open endpoint, or a function key pasted into a web page, lets anyone call your code. | Use Entra sign-in or API Management for real users, treat keys as shared secrets and rotate them. |
| Over-permissive managed identity | High | A compromised function inherits every role its identity holds. | Assign narrow roles at the smallest scope, and one identity per app. |
| Untrusted input used unsafely | High | Triggers deliver data from outside, which can carry injection payloads. | Check every trigger payload before use, and pass values to databases as parameters instead of building query strings. |
| Connection strings and keys in settings | Medium | Secrets in plain app settings are easy to copy and hard to rotate. | Use identity-based connections and Key Vault references. |
| Public network exposure | Medium | The app and its storage are reachable from the internet by default. | Access restrictions, private endpoints and virtual network integration. |
| Unbounded scale against a fragile dependency | Medium | Hundreds of parallel runs can knock over a database. | Cap instances and concurrency, and batch work through queues. |
| Unsupported runtime or model | Low–Med | Apps on retired runtimes or the .NET in-process model stop receiving fixes. | Keep a calendar of retirement dates and move apps before they pass. |
| Poison messages and duplicates | Low–Med | Failures and at-least-once delivery cause stuck or repeated work. | Monitor the poison queue and make handlers idempotent. |
| Sensitive data in logs | Low–Med | Verbose logging can store personal or secret data. | Log identifiers, not payloads, and set retention. |
Performance optimisation
- Create clients once. Reuse HTTP, storage and database clients across executions instead of building them per call.
- Pick the plan for the latency you need. Flex Consumption with always ready instances, or Premium, avoids most cold-start waits.
- Right-size instance memory on Flex Consumption: too small slows runs, too big wastes money.
- Keep HTTP calls short. Answer quickly, queue slow work and let the client check back.
- Tune batch and concurrency settings for queue and event triggers so you process quickly without flooding a database.
- Keep the package lean and use the current runtime, language worker and extension bundle versions.
- Run in the same Region as the storage, database and other services the function calls.
- Use Durable Functions for fan-out and long workflows instead of holding one function open.
Reduce monthly cost
FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Azure Functions.
- Start with Flex Consumption for new serverless apps. You pay for executions and memory-time, and a free monthly grant applies per subscription.
- Choose instance memory carefully; it sets the cost of each second a function runs.
- Use always ready sparingly. Warm instances are billed even when idle, so keep them to latency-critical functions.
- Cap maximum instances to limit both cost and pressure on dependencies.
- Batch and filter. Fewer executions for the same work means a smaller bill.
- Control monitoring cost. Sampling, log levels, retention and daily caps often matter more than compute.
- Do not forget the storage account. It is outside the free grant and is billed for operations and capacity.
- Pick Premium only when it pays off, for steady load, long runs or full network features; otherwise a serverless plan is usually cheaper.
- Delete unused apps and slots, and tag apps by team and product with budgets and alerts.
- Compare plans with real numbers in the Azure pricing calculator before committing to one.
Figures here come from Microsoft’s public pricing pages as of writing. Regions and plans change them, so check the live pages before you commit (see Pricing).
Security optimisation
- Use managed identities and identity-based connections for storage, queues, databases and Key Vault instead of connection strings.
- Keep remaining secrets in Azure Key Vault and reference them from app settings.
- Protect HTTP triggers with Microsoft Entra sign-in (built-in authentication) or API Management. Function keys are for service callers, not end users.
- Prefer private endpoints and virtual network integration, and restrict inbound access to known networks.
- Require HTTPS only and a modern minimum TLS version.
- Validate all input, treat trigger data as untrusted and avoid building queries or commands from it.
- Give each app least-privilege roles and review them regularly.
- Keep runtimes and packages current, and move .NET apps to the isolated worker model.
- Turn on Microsoft Defender for Cloud recommendations and review alerts.
- Send logs to Application Insights and Azure Monitor, and alert on failures, throttling and unusual call volumes.
Governance & compliance
Guardrails
- A tagging standard (Owner, Environment, CostCenter) enforced through Azure Policy
- Azure Policy to allow only approved Regions, runtimes and plans
- Management groups and landing zones for shared guardrails
- Budgets and cost alerts in Microsoft Cost Management
Continuous checks (Azure Policy examples)
- “Function apps should only be accessible over HTTPS”
- “Function apps should use managed identity”
- “Function apps should disable public network access”
- “Function apps should use the latest TLS version”
Policy names change over time, so search the built-in definitions for the current ones. For audits, use the Azure Activity log for who-changed-what, Microsoft Defender for Cloud for the regulatory compliance view and the Service Trust Portal for compliance reports. Microsoft’s attestations for Azure Functions cover the platform; your code, identities, data and app settings are yours to secure and to demonstrate.
Reduce carbon footprint
- Rely on idle scale-down. On serverless plans an app with no work consumes no compute.
- Keep always ready instances to a minimum, since warm instances keep resources reserved.
- Shorten each run. A function that finishes sooner, on less memory, uses less energy.
- Batch and filter events so the app wakes up only when there is real work.
- Prefer cleaner Regions where latency and data residency leave you room.
- Trim logging. Less data collected and stored saves energy and money.
- Measure it. The carbon optimization feature in the Azure portal and Microsoft’s emissions reporting estimate your impact; check which tool is current for your tenant.
Pricing
Purchase options
Flex Consumption Serverless
Pay for executions and memory-time on demand, with a monthly free grant per subscription. Optional always ready instances are billed for their baseline memory.
Consumption (older) Serverless
Billing follows executions and GB-seconds, and a free monthly grant is included. Linux apps on this plan retire on 30 September 2028, so new apps should start on Flex.
Premium Warm
Instances are kept pre-warmed and you pay for their vCPU and memory by the second, with full networking and no execution-time cap enforced.
Dedicated (App Service) Fixed
Run on an App Service plan you already pay for. Good when spare capacity exists or you need always-on behaviour.
What you actually pay for
- Executions and memory-time (GB-seconds) on serverless plans, or vCPU and memory time on Premium
- Always ready instance baseline, if used
- The host storage account (capacity and operations)
- Application Insights and Log Analytics data ingestion
- Networking: private endpoints, NAT or virtual network gateways, and data transfer out
Rates vary by Region and plan and are revised over time. Check the minimum billed time per execution on the page before you size very short functions. The Azure Functions pricing page and the Azure pricing calculator have the figures that apply today.
Important code references
A small queue-triggered function that saves each order to Azure Table Storage with an upsert, so a repeated message does no harm. A bad message raises an error, is retried, and finally moves to the poison queue. The CLI and Terraform tabs create a Flex Consumption app; the Python and C# tabs hold the function. Replace the placeholder names with your own.
# Resource group and the storage account the function app uses
az group create --name rg-func-dev --location centralindia
az storage account create \
--name stfuncorders001 \
--resource-group rg-func-dev \
--location centralindia \
--sku Standard_LRS \
--allow-blob-public-access false \
--min-tls-version TLS1_2
# A Flex Consumption function app running Python
az functionapp create \
--resource-group rg-func-dev \
--name func-orders-demo-001 \
--storage-account stfuncorders001 \
--flexconsumption-location centralindia \
--runtime python \
--runtime-version 3.12 \
--instance-memory 2048 \
--maximum-instance-count 40
# Identity-based connections: no connection strings in the settings
az functionapp identity assign --resource-group rg-func-dev --name func-orders-demo-001
PRINCIPAL_ID=$(az functionapp identity show --resource-group rg-func-dev --name func-orders-demo-001 --query principalId --output tsv)
STORAGE_ID=$(az storage account show --name stfuncorders001 --resource-group rg-func-dev --query id --output tsv)
az role assignment create --assignee-object-id "$PRINCIPAL_ID" --assignee-principal-type ServicePrincipal \
--role "Storage Queue Data Message Processor" --scope "$STORAGE_ID"
az role assignment create --assignee-object-id "$PRINCIPAL_ID" --assignee-principal-type ServicePrincipal \
--role "Storage Table Data Contributor" --scope "$STORAGE_ID"
az functionapp config appsettings set --resource-group rg-func-dev --name func-orders-demo-001 --settings \
"QueueConnection__queueServiceUri=https://stfuncorders001.queue.core.windows.net" \
"TABLE_ENDPOINT=https://stfuncorders001.table.core.windows.net"
# Deploy the code from the folder that holds function_app.py (Azure Functions Core Tools)
func azure functionapp publish func-orders-demo-001
# Uses the AzureRM 4.x provider. Assumes azurerm_resource_group.demo is defined elsewhere.
# Key-based access to the deployment container is shown for brevity: prefer identity-based access where your provider version supports it.
resource "azurerm_storage_account" "func" {
name = "stfuncorders001"
resource_group_name = azurerm_resource_group.demo.name
location = azurerm_resource_group.demo.location
account_tier = "Standard"
account_replication_type = "LRS"
allow_nested_items_to_be_public = false
min_tls_version = "TLS1_2"
}
resource "azurerm_storage_container" "package" {
name = "app-package"
storage_account_name = azurerm_storage_account.func.name
container_access_type = "private"
}
resource "azurerm_service_plan" "flex" {
name = "plan-func-orders"
resource_group_name = azurerm_resource_group.demo.name
location = azurerm_resource_group.demo.location
os_type = "Linux"
sku_name = "FC1"
}
resource "azurerm_function_app_flex_consumption" "orders" {
name = "func-orders-demo-001"
resource_group_name = azurerm_resource_group.demo.name
location = azurerm_resource_group.demo.location
service_plan_id = azurerm_service_plan.flex.id
storage_container_type = "blobContainer"
storage_container_endpoint = "${azurerm_storage_account.func.primary_blob_endpoint}${azurerm_storage_container.package.name}"
storage_authentication_type = "StorageAccountConnectionString"
storage_access_key = azurerm_storage_account.func.primary_access_key
runtime_name = "python"
runtime_version = "3.12"
instance_memory_in_mb = 2048
maximum_instance_count = 40
identity {
type = "SystemAssigned"
}
app_settings = {
QueueConnection__queueServiceUri = azurerm_storage_account.func.primary_queue_endpoint
TABLE_ENDPOINT = azurerm_storage_account.func.primary_table_endpoint
}
site_config {}
tags = {
Env = "dev"
Owner = "platform-team"
}
}
# function_app.py (requirements.txt: azure-functions, azure-data-tables, azure-identity)
import json
import logging
import os
import azure.functions as func
from azure.data.tables import TableServiceClient, UpdateMode
from azure.identity import DefaultAzureCredential
app = func.FunctionApp()
# Created once per worker process and reused by later executions
service = TableServiceClient(endpoint=os.environ["TABLE_ENDPOINT"], credential=DefaultAzureCredential())
orders = service.get_table_client("orders")
@app.queue_trigger(arg_name="msg", queue_name="orders", connection="QueueConnection")
def process_order(msg: func.QueueMessage) -> None:
# A bad message raises here, is retried, and finally lands in the "orders-poison" queue
order = json.loads(msg.get_body().decode("utf-8"))
entity = {"PartitionKey": "orders", "RowKey": str(order["order_id"]), "Total": order.get("total", 0)}
orders.upsert_entity(entity, mode=UpdateMode.REPLACE) # an upsert makes a repeated message harmless
logging.info("saved order %s", order["order_id"])
// dotnet add package Microsoft.Azure.Functions.Worker
// dotnet add package Microsoft.Azure.Functions.Worker.Sdk
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
// dotnet add package Azure.Data.Tables
// dotnet add package Azure.Identity
using System.Text.Json;
using Azure.Data.Tables;
using Azure.Identity;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(services =>
{
// One client for the whole process
services.AddSingleton(_ => new TableServiceClient(
new Uri(Environment.GetEnvironmentVariable("TABLE_ENDPOINT")!), new DefaultAzureCredential()));
})
.Build();
host.Run();
public class ProcessOrder
{
private readonly TableClient _orders;
private readonly ILogger<ProcessOrder> _logger;
public ProcessOrder(TableServiceClient service, ILogger<ProcessOrder> logger)
{
_orders = service.GetTableClient("orders");
_logger = logger;
}
[Function("ProcessOrder")]
public async Task Run([QueueTrigger("orders", Connection = "QueueConnection")] string message)
{
// A bad message throws here, is retried, and finally lands in the "orders-poison" queue
using var doc = JsonDocument.Parse(message);
var orderId = doc.RootElement.GetProperty("order_id").GetString()!;
await _orders.UpsertEntityAsync(new TableEntity("orders", orderId) { ["Body"] = message }, TableUpdateMode.Replace);
_logger.LogInformation("saved order {OrderId}", orderId);
}
}
Best videos to explore
Short walkthrough videos for this service are being prepared. They will appear here and load only when you press play. Until then, follow CloudBrum on YouTube for new videos.
Interview questions
BasicWhat problem does Azure Functions solve?
It runs small pieces of code when something happens: an HTTP request, a queue message, a timer tick. Azure provisions and scales the compute, so you look after only the code and its settings.
BasicWhat is the difference between a trigger and a binding?
A trigger starts a function and every function has exactly one. A binding is an optional declared connection to data: input bindings read data into the function and output bindings write results out, which saves you writing client code.
BasicWhich hosting plans are there?
Flex Consumption (the recommended serverless plan for new apps), Premium (pre-warmed instances and full networking), Dedicated on an App Service plan, and the older Consumption plan. Each differs in scaling, limits, networking and price.
IntermediateHow does Flex Consumption differ from the older Consumption plan?
Flex Consumption scales each function separately, lets you choose instance memory, supports virtual network integration and offers always ready instances. The older plan has a lower memory ceiling and shorter timeouts, and for Linux apps it has a published retirement date (30 September 2028).
IntermediateHow are failures handled for a queue-triggered function?
If the function throws, the message becomes visible again and is retried. After the configured number of attempts (five by default for Storage queues) it moves to a poison queue named after the original. Monitor that queue and make the function idempotent.
IntermediateWhat are Durable Functions used for?
They let you write stateful workflows in code: chaining steps, fanning out work in parallel and gathering results, waiting for an approval or an event, and retrying with automatic checkpoints. They suit processes that outlast a single function run.
AdvancedHow would you secure an HTTP-triggered function?
Put sign-in in front with Microsoft Entra built-in authentication or API Management, use private endpoints or access restrictions where users are internal, require HTTPS, validate input, and give the app a managed identity with narrow roles. Function keys alone are not user authentication.
AdvancedA web request must start a 20-minute process. Which pattern do you use?
An HTTP trigger must answer within roughly 230 seconds, so accept the request, hand the work to a queue or to a Durable Functions orchestration, and return 202 Accepted with a status address. The client polls that address, or you notify it when the work finishes. Durable Functions has this async HTTP API pattern built in.
AdvancedWhat changes when moving a .NET function from the in-process model to the isolated worker model?
Your code runs in a separate process with its own host builder and dependency injection, uses different packages and attributes, and can target newer .NET versions. Support for the in-process model ends on 10 November 2026, so plan the move.
Similar or alternative services on other clouds
| Capability | AWS | Azure | Google Cloud |
|---|---|---|---|
| Service | AWS Lambda | Azure Functions | Cloud Run functions |
| HTTP endpoint | Function URL, API Gateway | HTTP trigger, API Management | HTTP function, API Gateway |
| Event sources | SQS, SNS, EventBridge, S3, Kinesis | Queue Storage, Service Bus, Event Grid, Event Hubs | Pub/Sub, Eventarc, Cloud Storage |
| Multi-step workflows | Step Functions | Durable Functions | Workflows |
| Warm capacity | Provisioned concurrency, SnapStart | Always ready instances, Premium plan | Minimum instances |
| Longest run | 15 minutes | Depends on the plan: 10 minutes on Consumption, no enforced maximum on Flex and Premium | Longer for HTTP functions than for event-driven ones |
| Billing unit | Requests and GB-seconds | Executions and GB-seconds (Premium by vCPU and memory time) | Requests plus vCPU-seconds and GiB-seconds |
| Local development | AWS SAM CLI | Azure Functions Core Tools | Functions Framework |
Not sure a function is the right size? Compare with Azure Virtual Machines for servers you control, Azure Container Apps for containers that scale on events, Azure App Service for web apps with steady traffic, and Azure Logic Apps for low-code integration workflows.
Did you find this article helpful?
Your answer helps us improve this page for the next reader.
Sources and further reading
CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.
- Azure Functions documentationMicrosoft
- Azure Functions pricingMicrosoft
- Azure Functions hosting optionsMicrosoft
- Flex Consumption planMicrosoft
- Azure Functions triggers and bindingsMicrosoft
- Best practices for reliable Azure FunctionsMicrosoft
- Securing Azure FunctionsMicrosoft
- Guide for running C# Azure Functions in the isolated worker modelMicrosoft
- Azure Well-Architected FrameworkMicrosoft
- Service Level Agreements for Online ServicesMicrosoft
- Azure CLI reference: az functionappMicrosoft
- Terraform AzureRM provider: azurerm_function_app_flex_consumptionHashiCorp
