Getting Started with Azure Functions: Serverless Made Simple

Introduction

Azure Functions accelerates event-driven development by abstracting infrastructure so you can focus on code. This guide moves from a minimal HTTP trigger to an enterprise-ready architecture with durable orchestrations, secure secret management, observability, automation pipelines, and cost/performance tuning.

You will learn:

  • Core concepts: triggers, bindings, function app lifecycle
  • Choosing hosting plans (Consumption, Premium, Dedicated, Container Apps)
  • Implementing HTTP, Timer, Queue, Service Bus, Event Grid, Blob triggers
  • Durable Functions orchestration & state management patterns
  • Integration with Key Vault, Storage, Cosmos DB, Event Grid
  • Security (Managed Identity, Entra ID auth, network isolation)
  • Monitoring (Application Insights + OpenTelemetry)
  • Scaling & cost optimization strategies
  • CI/CD with GitHub Actions
  • Troubleshooting and resiliency patterns

Time to Read: 60–90 minutes
Skill Level: Beginner → Intermediate

Architecture Overview

flowchart LR subgraph Client APIClient[API Consumers] Portal[Admin Portal] end subgraph Ingress HTTP[HTTP Trigger] EventGrid[Event Grid Trigger] Timer[Timer Trigger] Queue[Queue Trigger] ServiceBus[Service Bus Trigger] Blob[Blob Trigger] end subgraph FuncApp[Function App] Func1[ProcessOrder] Func2[GenerateReport] Orchestrator[Durable Orchestrator] Activity1[Validate] Activity2[Enrich] Activity3[Persist] end subgraph Services[Azure Services] KV[(Key Vault)] Cosmos[(Cosmos DB)] Storage[(Blob Storage)] SB[(Service Bus)] AI[(App Insights)] end Client --> HTTP EventGrid --> Func1 Queue --> Func2 ServiceBus --> Orchestrator Blob --> Func2 HTTP --> Orchestrator Orchestrator --> Activity1 Orchestrator --> Activity2 Orchestrator --> Activity3 Activity3 --> Cosmos Activity2 --> Storage Func1 --> SB Func2 --> KV FuncApp --> AI

Prerequisites

Requirement Details
Subscription Azure subscription with permissions to create resource group
Tools Azure CLI, VS Code, Node.js or .NET SDK, GitHub CLI
Accounts Entra ID user with contributor role, GitHub account for CI/CD
Monitoring Application Insights workspace or direct component creation

Install tooling:

winget install Microsoft.AzureCLI
winget install Microsoft.VisualStudioCode
winget install Git.Git

Step-by-Step Implementation

1. Resource Group & Core Services

az group create --name rg-func-intro --location eastus
az storage account create --name funcintrostore --resource-group rg-func-intro --sku Standard_LRS
az monitor app-insights component create --app func-intro-ai --location eastus --resource-group rg-func-intro --application-type web

2. Create Function App (Consumption)

az functionapp create --resource-group rg-func-intro --consumption-plan-location eastus --runtime dotnet --functions-version 4 --name func-intro-app --storage-account funcintrostore --app-insights func-intro-ai

3. Add Managed Identity & Key Vault

az keyvault create --name kv-func-intro --resource-group rg-func-intro --location eastus
az functionapp identity assign --name func-intro-app --resource-group rg-func-intro
$principalId = az functionapp identity show -g rg-func-intro -n func-intro-app --query principalId -o tsv
az keyvault set-policy -n kv-func-intro --object-id $principalId --secret-permissions get list

4. Sample HTTP Trigger (C#)

public static class HttpHello
{
    [FunctionName("HttpHello")]
    public static IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "hello")] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("Processing HttpHello request");
        var name = req.Query["name"];
        return new OkObjectResult(new { message = $"Hello {name}" });
    }
}

5. Timer Trigger (Maintenance)

public static class NightlyMaintenance
{
    [FunctionName("NightlyMaintenance")]
    public static async Task Run([TimerTrigger("0 0 2 * * *")]TimerInfo timer, ILogger log)
    {
        log.LogInformation("Nightly maintenance started");
        // purge temp blobs / archive logs
        await Task.Delay(250);
        log.LogInformation("Nightly maintenance complete");
    }
}

6. Durable Orchestration Pattern

public static class OrderOrchestrator
{
    [FunctionName("OrderOrchestrator")]
    public static async Task<object> Run([OrchestrationTrigger] IDurableOrchestrationContext ctx)
    {
        var order = ctx.GetInput<Order>();
        var valid = await ctx.CallActivityAsync<bool>("ValidateOrder", order);
        if(!valid) return new { status = "Rejected" };
        var enriched = await ctx.CallActivityAsync<Order>("EnrichOrder", order);
        await ctx.CallActivityAsync("PersistOrder", enriched);
        await ctx.CallActivityAsync("NotifyQueue", enriched.Id);
        return new { status = "Completed", id = enriched.Id };
    }
}

7. Local Development & Debugging

func init src --dotnet
cd src
func new --name HttpHello --template "HTTP trigger" --authlevel Function
func start

Browse http://localhost:7071/api/hello?name=Azure.

Security & Identity

Aspect Best Practice Implementation
Secrets Use Key Vault + Managed Identity Azure.Identity client + secret retrieval
Auth Level Avoid Anonymous unless public webhook Use Function or User level
Network Private endpoints for Premium / VNet integration App Service VNet integration
Principle of Least Privilege Separate function apps by domain Resource group & identity isolation
Data Access Use role assignments not connection strings RBAC on Storage, Cosmos DB

Key Vault retrieval example (C#):

var client = new SecretClient(new Uri(Environment.GetEnvironmentVariable("KEY_VAULT_URI")), new DefaultAzureCredential());
var secret = client.GetSecret("ApiKey").Value.Value;

Monitoring & Telemetry

Enable logging & traces:

builder.Services.AddLogging();
// For isolated process, configure host.json + app insights connection string

Kusto query (failed functions):

requests
| where cloud_RoleName == "func-intro-app"
| where success == false
| summarize count() by operation_Name, bin(timestamp, 1h)

Performance & Cost Optimization

Strategy Applies To Benefit
Bundle Functions by domain All Reduced cold start variance
Use async I/O HTTP / Queue Lower thread usage
Avoid heavy static constructors All Faster warm / scale
Durable fan-out/fan-in Orchestrations Parallel efficiency
Premium plan for steady load High throughput workloads Predictable performance
Caching configuration HTTP Less Key Vault latency

CI/CD Pipeline

name: deploy-azure-functions
on:
  push:
    paths: [ 'src/**' ]
    branches: [ main ]
jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'
      - name: Build
        run: dotnet build src/FunctionApp.csproj -c Release
      - name: Publish
        run: dotnet publish src/FunctionApp.csproj -c Release -o publish
      - name: Azure Login
        uses: azure/login@v2
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Deploy
        uses: azure/functions-action@v1
        with:
          app-name: func-intro-app
          package: publish

Troubleshooting Matrix

Symptom Cause Diagnosis Resolution
Cold starts Infrequent invocations App Insights startup trace Warmup ping or Premium plan
401 errors Missing function key Check Host keys Regenerate & update client
Failed durable instances Activity exception DurableFunctionsHubHistory table Retry pattern / circuit breaker
Storage throttling High concurrency Metrics: Storage transactions Upgrade tier / optimize batching
Secret retrieval latency Frequent calls to Key Vault App Insights dependency timing Cache secret until expiry window

Resiliency Patterns

  • Retries with exponential backoff for transient external calls.
  • Circuit breaker around enrichment APIs.
  • Poison queue handling: move failed messages to dead-letter queue and alert.

Image References

Azure Functions Architecture
Durable Functions Patterns
Key Vault Conceptual

References