Functions is the serverless glue for events, scheduled jobs and lightweight APIs on Azure.
Azure Functions runs small pieces of code in response to events. Each function has exactly one trigger (HTTP request, timer, queue or Service Bus message, blob change, Event Grid event, Cosmos DB change feed) and optional input/output bindings that read or write other services declaratively.
A function app groups functions that deploy and scale together. It needs a storage account for its own state. Hosting plans:
- Flex Consumption: the recommended serverless plan; per-execution billing, fast scale, scale to zero, optional always-ready instances and VNet integration.
- Consumption: the older serverless plan, with a 10-minute maximum execution time.
- Premium: pre-warmed instances (no cold start), VNet, longer runs.
- Dedicated: runs on an App Service plan you already pay for.
Code models are language specific: Python uses the v2 model with decorators; .NET uses the isolated worker model. For the connection to triggers, prefer identity-based connections (<name>__fullyQualifiedNamespace settings plus a managed identity) over connection strings.
Design rules: keep functions short and idempotent (triggers deliver at least once), push long workflows to Durable Functions, and don't hold state in memory between invocations.
Example
# function_app.py (Python v2 programming model)
import json, logging
import azure.functions as func
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
@app.route(route="orders", methods=["POST"])
@app.queue_output(arg_name="msg", queue_name="orders", connection="Storage")
def create_order(req: func.HttpRequest, msg: func.Out[str]) -> func.HttpResponse:
order = req.get_json()
msg.set(json.dumps(order)) # enqueue via output binding
return func.HttpResponse(status_code=202)
@app.queue_trigger(arg_name="m", queue_name="orders", connection="Storage")
def process_order(m: func.QueueMessage) -> None:
logging.info("processing %s", m.get_json()["id"])
@app.timer_trigger(arg_name="t", schedule="0 0 2 * * *") # 02:00 UTC daily
def nightly(t: func.TimerRequest) -> None:
logging.info("nightly cleanup")Remember
- One trigger per function; bindings read/write other services
- Flex Consumption is the default serverless choice
- Triggers are at-least-once: make handlers idempotent
- Use Durable Functions for long or stateful workflows
Watch out for
- Running long jobs on the Consumption plan and hitting the execution time limit.