Domain 3 β€” Module 4 of 6 67%
20 of 27 overall
Domain 3: Connect to and consume Azure services Free ⏱ ~13 min read

Azure Functions: Triggers + Bindings

Serverless APIs and event handlers without writing the plumbing. Trigger types, input and output bindings, the binding expression syntax, and how AI workloads use Functions for thin glue between Azure services.

What Functions actually does for you

Simple explanation

Azure Functions runs small pieces of code in response to events, with the boilerplate written for you. Want to react to a Service Bus message? Write a function with a Service Bus trigger β€” the runtime handles connection, locking, retries, even parallelism.

The big productivity win is bindings. An input binding reads from a service (e.g., Cosmos DB) and hands your function the result. An output binding takes a value your function returns and writes it somewhere (e.g., a Service Bus queue). You write business logic; the framework writes the plumbing.

For AI back-ends Functions sit between Azure services as thin glue β€” embed-on-blob-create, summarise-on-cosmos-update, schedule-nightly-cleanup.

A function in three flavours

HTTP trigger (the canonical serverless API)

# Python (v2 programming model)
import azure.functions as func
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

@app.route(route="embed", methods=["POST"])
def embed(req: func.HttpRequest) -> func.HttpResponse:
    body = req.get_json()
    text = body["text"]
    embedding = generate_embedding(text)
    return func.HttpResponse(json.dumps({"embedding": embedding}), mimetype="application/json")

Service Bus queue trigger

@app.service_bus_queue_trigger(
    arg_name="msg",
    queue_name="image-jobs",
    connection="ServiceBusConnection",
)
def process_image_job(msg: func.ServiceBusMessage):
    payload = json.loads(msg.get_body().decode())
    embed_image(payload["url"])

The runtime opens the connection, holds the message lock, calls your function, and (depending on disposition) completes/abandons the message automatically. No Receive/Complete boilerplate.

Cosmos DB change-feed trigger + output binding

@app.cosmos_db_trigger(
    arg_name="docs",
    container_name="articles",
    database_name="knowledge",
    connection="CosmosConnection",
    lease_container_name="articles-leases",
)
@app.cosmos_db_output(
    arg_name="output_doc",
    container_name="article_embeddings",
    database_name="knowledge",
    connection="CosmosConnection",
)
def embed_articles(docs: func.DocumentList, output_doc: func.Out[func.Document]):
    for doc in docs:
        if "embedding" not in doc:
            embedding = generate_embedding(doc["body"])
            output_doc.set(func.Document.from_dict({
                "id": f"{doc['id']}-emb",
                "article_id": doc["id"],
                "embedding": embedding,
            }))

Three Azure services touched (Cosmos read trigger, Cosmos write output) β€” zero SDK calls in your code.

Trigger types you must know

The six triggers that cover most AI-200 questions. Pick the one that matches the source of work.
FeatureHTTPTimerService BusEvent GridCosmos DBBlob
Fires whenRequest hits the function URLOn a CRON scheduleMessage arrives in queue or topic subscriptionEvent Grid event is delivered to the functionDocument created or updated (change feed)Blob created or updated
AuthFunction key, Microsoft Entra (Easy Auth), or anonymousN/AConnection string or managed identityWebHook endpoint with validationConnection string or managed identityConnection string or managed identity
Best forWeb APIsScheduled jobs (cleanup, refresh)Reliable async workReactive integration across AzureReact to data changesFile ingestion (use with Event Grid)

Input and output bindings

@app.route(route="article/{id}")
@app.cosmos_db_input(
    arg_name="article",
    container_name="articles",
    database_name="knowledge",
    connection="CosmosConnection",
    id="{id}",                  # bind to the route parameter
    partition_key="{id}",
)
@app.queue_output(
    arg_name="qout",
    queue_name="audit",
    connection="StorageConnection",
)
def get_article(req, article: func.Document, qout: func.Out[str]):
    qout.set(json.dumps({"action": "read", "id": req.route_params["id"]}))
    return func.HttpResponse(article.to_json())

Notice the binding expressions:

  • id="{id}" β€” the route parameter named id
  • partition_key="{id}" β€” same value bound twice
  • The handler itself receives the doc as article, no SDK call

Common binding expression patterns:

ExpressionResolves to
{id}A route parameter
{queueTrigger}The current message body
{rand-guid}A random GUID per execution
{datetime:yyyy-MM-dd}The current UTC date in the format
{sys.utcNow}UTC timestamp
%MyAppSetting%A value from app settings

Authentication options

AuthWhere it appliesWhen
Function keyHTTP triggersQuick start, simple keys per function
App-wide host keyAll HTTP triggersConvenience
AnonymousHTTP triggersPublic webhooks
Microsoft Entra (Easy Auth)HTTP triggersProduction β€” sign-in, JWT validation, role checks
Managed identity for service connectionsTriggers and bindingsRecommended β€” avoid connection strings
# Use managed identity for the Service Bus trigger connection
az functionapp config appsettings set \
  --name roo-fn -g roo-prod \
  --settings "ServiceBusConnection__fullyQualifiedNamespace=roo-sb.servicebus.windows.net"

The __fullyQualifiedNamespace suffix tells the host to use Microsoft Entra credentials (the function’s managed identity) instead of a connection string.

Function chaining vs Durable Functions

For multi-step orchestration (call A, then B, with retries and state), Functions has a sibling: Durable Functions. It adds:

  • Orchestrator functions that describe a workflow as code
  • Activity functions that do the actual work
  • Durable Entities for stateful actors
  • Built-in fan-out/fan-in, retries, timers, sub-orchestrations

Durable is overkill for β€œreact to event β†’ do one thing” workflows β€” that’s plain Functions territory. It shines when an AI workflow is a multi-step chain (extract β†’ embed β†’ enrich β†’ store β†’ notify) with retries and possible long waits.

Key terms

Question

What is a trigger in Azure Functions?

Click or press Enter to reveal answer

Answer

The thing that causes a function to run. Each function has exactly one trigger. Common triggers: HTTP, Timer, Service Bus (queue/topic), Event Grid, Cosmos DB change feed, Blob created, Event Hubs message.

Click to flip back

Question

What's the difference between an input binding and an output binding?

Click or press Enter to reveal answer

Answer

An input binding reads from a service and supplies the value to your function (e.g., a Cosmos doc retrieved by id). An output binding takes a value your function produces and writes it to a service (e.g., enqueue to Service Bus). Both are declarative β€” no SDK code needed.

Click to flip back

Question

What's a binding expression?

Click or press Enter to reveal answer

Answer

A placeholder syntax that pulls values from the trigger context, route, app settings, or system functions. Examples: `{id}` (route parameter), `{queueTrigger}` (message body), `%MyAppSetting%` (app setting), `{rand-guid}` (random GUID per run).

Click to flip back

Question

How do you authenticate a Service Bus trigger to its namespace using managed identity?

Click or press Enter to reveal answer

Answer

Set `<ConnectionPrefix>__fullyQualifiedNamespace=<namespace>.servicebus.windows.net` in app settings. The Functions host reads this convention as 'use Microsoft Entra credentials' and authenticates with the function's managed identity.

Click to flip back

Question

When should you use Durable Functions vs plain Functions?

Click or press Enter to reveal answer

Answer

Plain Functions for single-step reactions (event β†’ action). Durable Functions for multi-step orchestration with state, retries, sub-orchestrations, and long-waiting activities β€” typical of multi-step AI workflows like extract β†’ embed β†’ enrich β†’ store β†’ notify.

Click to flip back

Knowledge check

Knowledge Check

Mira wants a function that reads a Cosmos document by route parameter, modifies it, and writes the updated doc back. What's the cleanest pattern?

Knowledge Check

Theo's function processes Service Bus messages. The connection currently uses a connection string in app settings. He wants to switch to managed identity. What's the right pattern?

Knowledge Check

Lin's AI workflow is: extract text from PDF β†’ call OpenAI to summarise β†’ write summary to Cosmos β†’ notify Slack. The total can take 30-90 seconds with multiple retry-able steps. Which Functions pattern fits best?