All Articles
Azure.NETServerless

Azure Functions: A Practical Guide for .NET Developers

Deploying serverless workloads on Azure Functions with .NET — triggers, bindings, local development, and CI/CD integration.

2026-03-05·10 min read

Azure Functions is Microsoft's serverless compute platform. You deploy a function, configure a trigger, and Azure handles scaling, infrastructure, and billing by execution. For .NET developers, it's a natural fit — you write C#, use the same NuGet ecosystem, and get the same IDE experience.

The Basics: Triggers and Bindings

Every Azure Function needs a trigger — the event that causes it to run. Common triggers include:

  • HTTP — Runs on an incoming HTTP request (REST API)
  • Timer — Runs on a CRON schedule
  • Service Bus — Runs when a message arrives on a queue or topic
  • Blob Storage — Runs when a file is created or modified

Bindings are optional. They declaratively connect your function to Azure services for input or output — no SDK code required:

[Function("ProcessOrder")]
[ServiceBusOutput("orders-processed", Connection = "ServiceBusConnection")]
public string Run(
    [ServiceBusTrigger("orders-incoming", Connection = "ServiceBusConnection")]
    string message,
    FunctionContext context)
{
    var logger = context.GetLogger("ProcessOrder");
    logger.LogInformation("Processing order: {Message}", message);
    return message; // output binding sends this to orders-processed
}

The return value goes to the output binding — no manual SDK call needed to put a message on a queue.

The Isolated Worker Model

Azure Functions for .NET now uses the Isolated Worker Model by default. Your function runs in a separate .NET process from the Functions host, which means:

  • Full control over the .NET version (target .NET 8 or 9 without waiting for host support)
  • Standard dependency injection via HostBuilder
  • Middleware support
var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        services.AddSingleton<IOrderService, OrderService>();
        services.AddDbContext<AppDbContext>(options =>
            options.UseSqlServer(Environment.GetEnvironmentVariable("SqlConnection")));
    })
    .Build();

host.Run();

Services registered here are available for injection into your function classes.

Local Development

The Azure Functions Core Tools (func) run the Functions host locally. Paired with Azurite (the Azure Storage emulator) and the Service Bus emulator, you can develop and test most triggers locally without touching Azure.

npm install -g azure-functions-core-tools@4
func start

Use local.settings.json for environment variables locally — the equivalent of Application Settings in Azure:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "SqlConnection": "Server=localhost;Database=Orders;..."
  }
}

Never commit local.settings.json — it contains secrets. Add it to .gitignore.

Deployment with CI/CD

A typical GitHub Actions pipeline for Azure Functions:

- name: Build
  run: dotnet publish -c Release -o ./output

- name: Deploy to Azure Functions
  uses: Azure/functions-action@v1
  with:
    app-name: my-functions-app
    package: ./output
    publish-profile: ${{ secrets.AZURE_FUNCTIONAPP_PUBLISH_PROFILE }}

Alternatively, use Azure CLI or Bicep for infrastructure-as-code deployments. The publish profile approach is quick for getting started; managed identity with OIDC is the production-grade choice.

Cold Starts and the Consumption Plan

On the Consumption plan, Functions scale to zero when idle. The first invocation after a period of inactivity incurs a cold start — typically 1–3 seconds for .NET. Strategies to mitigate:

  • Use the Flex Consumption or Premium plan for pre-warmed instances
  • Keep function assemblies small (trim unused packages)
  • Use the Isolated Worker model (faster than in-process for cold starts)

When to Use Azure Functions

Azure Functions excel at:

  • Lightweight HTTP APIs with variable traffic
  • Background jobs triggered by queues or timers
  • Event-driven processing (file uploads, database changes)
  • Glue code connecting Azure services

For long-running processes, stateful workflows, or high-throughput scenarios with consistent load, Azure Container Apps or App Service is often a better fit.