Overview
Azure Functions is Microsoft’s serverless compute service that enables event-driven code execution without managing infrastructure. It supports multiple programming languages including C#, JavaScript, TypeScript, Python, Java, PowerShell, and Go, with triggers from HTTP requests, timers, queues, blobs, and many other Azure services.
Azure Functions provides a flexible hosting model with Consumption (pay-per-execution), Premium (pre-warmed instances), and Dedicated plans. Key features include input/output bindings for declarative service integration, Durable Functions for stateful workflows, and seamless integration with Azure DevOps and GitHub Actions for CI/CD.
Installation
# macOS
brew tap azure/functions
brew install azure-functions-core-tools@4
# Linux (Ubuntu/Debian)
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/
sudo sh -c 'echo "deb https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-get update && sudo apt-get install azure-functions-core-tools-4
# Windows
npm install -g azure-functions-core-tools@4
# Verify
func --version
Create Function App
# Login to Azure
az login
# Create resource group
az group create --name myResourceGroup --location eastus
# Create storage account
az storage account create --name mystorageacct \
--resource-group myResourceGroup --location eastus --sku Standard_LRS
# Create function app
az functionapp create --name myFunctionApp \
--resource-group myResourceGroup \
--storage-account mystorageacct \
--consumption-plan-location eastus \
--runtime node --runtime-version 20 \
--functions-version 4
Project Setup
# Create new project
func init MyFunctionProject --worker-runtime node --language typescript
# Create a new function
cd MyFunctionProject
func new --name HttpTrigger --template "HTTP trigger"
# Run locally
func start
# Run with specific port
func start --port 7072
Function Templates
HTTP Trigger (TypeScript)
// src/functions/httpTrigger.ts
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
export async function httpTrigger(
request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || (await request.text()) || 'World';
return { body: `Hello, ${name}!` };
}
app.http('httpTrigger', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: httpTrigger,
});
Timer Trigger (Python)
# function_app.py
import azure.functions as func
import logging
app = func.FunctionApp()
@app.timer_trigger(schedule="0 */5 * * * *", arg_name="timer")
def timer_trigger(timer: func.TimerRequest) -> None:
if timer.past_due:
logging.info('Timer is past due!')
logging.info('Python timer trigger executed.')
Queue Trigger with Blob Output (C#)
[Function("QueueProcessor")]
[BlobOutput("output/{id}.json")]
public static string Run(
[QueueTrigger("myqueue")] QueueMessage message,
FunctionContext context)
{
var logger = context.GetLogger("QueueProcessor");
logger.LogInformation($"Processing: {message.Body}");
return $"{{\"processed\": true, \"id\": \"{message.MessageId}\"}}";
}
Triggers and Bindings
Common Triggers
| Trigger | Description |
|---|
| HTTP | REST API endpoints |
| Timer | Cron-scheduled execution |
| Queue Storage | Azure Queue messages |
| Blob Storage | File upload/change events |
| Service Bus | Queue/topic messages |
| Event Hub | Stream processing |
| Event Grid | Event-driven triggers |
| Cosmos DB | Document change feed |
Binding Examples (TypeScript)
// Blob input binding
app.http('readBlob', {
methods: ['GET'],
authLevel: 'anonymous',
extraInputs: [
input.storageBlob({ path: 'container/{name}', connection: 'AzureWebJobsStorage' })
],
handler: async (request, context) => {
const blob = context.extraInputs.get('blobInput');
return { body: blob };
},
});
// Queue output binding
app.http('enqueue', {
methods: ['POST'],
authLevel: 'anonymous',
extraOutputs: [
output.storageQueue({ queueName: 'myqueue', connection: 'AzureWebJobsStorage' })
],
handler: async (request, context) => {
const body = await request.json();
context.extraOutputs.set('queueOutput', body);
return { body: 'Enqueued' };
},
});
Deployment
# Deploy from local project
func azure functionapp publish myFunctionApp
# Deploy with build
func azure functionapp publish myFunctionApp --build remote
# Deploy specific slot
func azure functionapp publish myFunctionApp --slot staging
# Deploy using ZIP
az functionapp deployment source config-zip \
--resource-group myResourceGroup \
--name myFunctionApp \
--src function-app.zip
Configuration
Application Settings
# Set app settings
az functionapp config appsettings set \
--name myFunctionApp \
--resource-group myResourceGroup \
--settings "DB_CONNECTION=Server=myserver;Database=mydb"
# Set from Key Vault
az functionapp config appsettings set \
--name myFunctionApp \
--resource-group myResourceGroup \
--settings "SECRET=@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret)"
# Local settings (local.settings.json)
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"DB_CONNECTION": "Server=localhost;Database=mydb"
}
}
Host Configuration (host.json)
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"maxTelemetryItemsPerSecond": 20
}
},
"logLevel": {
"default": "Information",
"Function.MyFunction": "Debug"
}
},
"functionTimeout": "00:10:00",
"extensions": {
"queues": {
"batchSize": 16,
"maxPollingInterval": "00:00:02",
"visibilityTimeout": "00:00:30",
"maxDequeueCount": 5
}
}
}
Durable Functions
import * as df from 'durable-functions';
import { app } from '@azure/functions';
// Orchestrator
df.app.orchestration('orderOrchestrator', function* (context) {
const order = context.df.getInput();
const validation = yield context.df.callActivity('validateOrder', order);
if (!validation.valid) return { status: 'invalid' };
const payment = yield context.df.callActivity('processPayment', order);
// Fan-out/fan-in
const tasks = order.items.map((item) =>
context.df.callActivity('processItem', item)
);
const results = yield context.df.Task.all(tasks);
yield context.df.callActivity('sendNotification', { order, results });
return { status: 'completed', results };
});
// Activity
df.app.activity('validateOrder', { handler: (input) => {
return { valid: input.amount > 0 };
}});
// HTTP starter
app.http('startOrder', {
route: 'orders/start',
handler: df.app.durableClient(async (request, client) => {
const body = await request.json();
const instanceId = await client.startNew('orderOrchestrator', { input: body });
return client.createCheckStatusResponse(request, instanceId);
}),
});
CLI Commands
| Command | Description |
|---|
func init | Initialize new project |
func new | Create new function |
func start | Run locally |
func azure functionapp publish <app> | Deploy |
az functionapp list | List function apps |
az functionapp show -n <app> -g <rg> | Get app details |
az functionapp restart -n <app> -g <rg> | Restart app |
az functionapp log tail -n <app> -g <rg> | Stream logs |
Monitoring
# Stream logs
az functionapp log tail --name myFunctionApp --resource-group myResourceGroup
# Application Insights query
az monitor app-insights query \
--app myAppInsights \
--analytics-query "requests | where success == false | top 10 by timestamp desc"
Troubleshooting
| Issue | Solution |
|---|
| Function not triggering | Check trigger configuration; verify connection strings |
| Cold start slow | Use Premium plan with pre-warmed instances; reduce dependencies |
| Timeout errors | Increase functionTimeout in host.json; use Durable Functions for long tasks |
| Binding errors | Verify binding extension is installed; check connection string names |
| Deployment fails | Check runtime version matches; verify storage account access |
| Local debugging issues | Ensure local.settings.json exists; check storage emulator is running |
| Out of memory | Increase plan tier; optimize memory usage; reduce concurrent executions |
| CORS errors | Configure CORS in Azure Portal or via az functionapp cors add |