Azure Functions
Azure Functions is Azure's serverless compute service: you write a single function, declare what event should trigger it, and Azure runs it — provisioning, scaling, and de-provisioning the machinery underneath without you naming a server. You are billed for execution, not for hardware sitting idle.
Names: the service has always been Azure Functions. What has changed underneath it is the
vocabulary that actually matters: the hosting plan. The original Consumption plan has been
joined by Flex Consumption, Premium (also written Elastic Premium, SKUs EP1–EP3), and
Dedicated (an ordinary App Service Plan). For .NET, the older in-process execution model is
being retired in favour of the isolated worker model — if you find a tutorial with
[FunctionName] and a Run method taking an ILogger injected by the host, you are reading
in-process-era material. ⚠️ verify the current in-process retirement date against current Azure
docs.
What it is and where it fits
A function is a piece of code with a trigger — an HTTP request, a message on a queue, a timer, a blob landing, an Event Grid event. You do not write the loop that waits for the event, you do not write the retry, and you do not write the scaling logic. The Functions host does all three, and hands your code the event as a parameter.
The problem it solves is idle. A web app that receives one request a minute still needs a process running, a machine to run it on, and a bill for that machine 1,440 minutes a day. Functions collapse that to the seconds your code actually executes. The corollary — and this is the part that decides architectures — is that the platform must be free to stop running you, which is where cold starts, statelessness, and execution timeouts come from. Every constraint in this topic descends from that one bargain.
Azure's compute catalogue overlaps itself badly, and "should this be a Function?" is one of the two or three most common design arguments on the platform. The neighbours, separated in a line each:
- App Service — a long-running web app you bring code to. Choose it when the workload is a conventional HTTP application with steady traffic; Functions and App Service actually share the same underlying resource type, which is why their vocabulary rhymes.
- Azure Container Apps — a container-shaped runtime that also scales to zero, with KEDA and Dapr. Choose it when you have a container, need more than one process, or want microservice-style networking. Functions can also run on Container Apps, which blurs the line deliberately.
- Logic Apps — connector-driven, low-code integration with a visual designer. Choose it when the work is "call SAP, transform, put it in SharePoint" rather than "run my code".
- Azure Kubernetes Service — choose it when you already run Kubernetes and want everything in one place; you are trading a great deal of operational surface for that consistency.
- WebJobs — the ancestor. Functions is built on the WebJobs SDK; you should not start anything new on WebJobs.
The honest summary: Functions is the right default for event-driven glue and bursty work, and the wrong default for anything long-running, stateful, or latency-critical at low traffic.
Key facts at a glance
| Category | Compute — serverless / FaaS |
| Resource provider | Microsoft.Web/sites with kind = functionapp (plus Microsoft.Web/serverfarms for the plan) |
| Scope | Regional; the function app is a resource-group-scoped resource with a globally unique hostname |
| SKU / tier axis | The hosting plan — Consumption, Flex Consumption, Premium (EP1–EP3), Dedicated (App Service Plan B/S/Pv3), App Service Environment, and Container Apps hosting. This choice drives cold start, VNet support, timeout, scale limits, and cost far more than your code does |
| Unit of billing | Consumption / Flex: executions + GB-seconds (memory × duration), with a monthly free grant ⚠️ verify current grant. Premium / Dedicated: per-instance per-hour, whether or not anything is running |
| Hard dependency | A general-purpose storage account (AzureWebJobsStorage) — the host uses it for triggers, leases, timers, and often the deployed package. Delete it and the app stops working |
| SLA posture | Consumption has historically had no SLA on individual executions; Premium/Dedicated inherit App Service's SLA ⚠️ verify against current Azure docs |
| Usual companions | Storage, Application Insights, Key Vault, Service Bus / Event Grid / Event Hubs, API Management, managed identity |
| Primary alternative | Azure Container Apps (containerised, scale-to-zero) or App Service (steady HTTP) |
| AWS analogue | Lambda — a good analogy for the programming model, a poor one for hosting, because Lambda has no equivalent of "the plan" |
When to use it
- Event-driven glue. A blob lands, a message arrives, a webhook fires, something must happen. This is Functions' home ground and nothing else in the catalogue is as cheap or as direct.
- Bursty or unpredictable traffic. Scaling from zero to hundreds of instances and back is the feature you are actually paying for.
- Scheduled work. A timer trigger replaces a cron VM, and the singleton behaviour across instances is handled for you.
- Lightweight APIs where a few hundred milliseconds of occasional cold start is acceptable — or where you have moved to a plan that removes cold start.
- Orchestration of your own code via Durable Functions, when the workflow is code-shaped rather than connector-shaped.
When not to use it
- Long-running work. Every plan has a timeout, and on Consumption it is short. A two-hour ETL job is a Container Apps job, a Batch job, or a Durable Function that has been decomposed — not one function with a raised timeout.
- Latency-critical, low-traffic HTTP. If a 1–10 second cold start would breach your SLO and your traffic won't keep instances warm, you need Premium/Flex always-ready instances — at which point you are paying for idle anyway and should compare honestly with App Service.
- Stateful or session-bound work. Instances appear and vanish. Anything you keep in memory is a cache at best.
- Chatty, high-volume, steady traffic. Serverless per-execution pricing stops being cheap well before it stops being convenient. At constant load, a right-sized plan is usually less expensive.
- Heavy dependencies or exotic runtimes that make the deployment package large and cold starts worse. That's a container workload.
- "Just one more thing in the same app." A function app that has grown thirty unrelated functions shares one scale decision, one deployment, one set of app settings, and one blast radius.
What this topic covers
| Sub-topic | What it covers |
|---|---|
| What & Why | The problem Functions kills, the compute-catalogue decision, the Lambda analogy and exactly where it breaks, and the honest anti-patterns |
| Core Concepts | Function app, plan, triggers and bindings, the storage account, runtime versions and language models, keys, slots, and the SKU trap |
| Architecture | The scale controller, what happens during an invocation, cold start anatomy, control plane vs. data plane, and the failure modes |
| Getting Started | One HTTP-triggered function, three ways — portal, az CLI, and a minimal Terraform snippet — plus teardown |
| Deployment | A parameterised Terraform module, remote state, an Ansible playbook, the Bicep equivalent, OIDC-based CI/CD, environments, slot swaps, rollback, and drift |
| Integrations | Storage, Service Bus, Event Grid, Event Hubs, Key Vault, API Management, Cosmos DB, and the two glue mechanisms that recur everywhere |
| Production | Security, cost, scaling and quota scopes, observability, and reliability — the five pillars that separate a demo from a running system |
| Interview Questions | Three tiers of questions with answer keys, from "what is serverless" to "someone edited this in the portal, now what" |
| Glossary & Cheatsheet | Every term in one line each, the commands you'll actually type, the resource ID shape, and the limits worth memorising |
Three ideas worth carrying into every other page
The plan is the service. Two function apps running byte-identical code can differ by an order of magnitude in latency, an order of magnitude in cost, and entirely in whether they can reach a private database — purely because one is on Consumption and one is on Premium. When someone says "we use Azure Functions", the useful follow-up question is always "on which plan?"
There is a storage account under every function app, and it is not optional. The host stores
trigger metadata, timer schedules, singleton and partition leases, and usually the deployment package
itself in AzureWebJobsStorage. Lock that storage account behind a firewall without configuring
access properly and the app stops triggering in ways that look like a code bug. This dependency has
no Lambda equivalent and it surprises everyone exactly once.
A function app is one App Service site. The resource type is Microsoft.Web/sites — the same one
App Service uses. That's why Functions has app settings, deployment slots, Kudu/SCM, a *.azurewebsites.net
hostname, and an App Service Plan. Most "how do I do X with Functions" answers are App Service answers.
Resource groups, subscriptions, ARM, and RBAC inheritance are explained once in Foundations rather than repeated here.
Reading paths
New to serverless — What & Why → Core Concepts → Getting Started. Build one, delete it, then come back for Architecture.
Coming from Lambda — skim What & Why for where the analogy breaks, then go straight to Core Concepts for the plan/app/trigger model and Architecture for the scale controller, which has no Lambda equivalent.
Need to ship this week — Deployment first, then Production. Getting Started is deliberately throwaway; don't build on it.
Interview or certification prep — Core Concepts, Architecture, and Interview Questions. The plan-comparison question and the cold-start question come up in almost every AZ-204 interview.
Chasing a cost surprise — the cost section of Production, then the plan discussion in Core Concepts. An idle Premium plan and an over-chatty storage-triggered function are the two usual culprits.
Next: What & Why →