# Azure Functions

> Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable Functions, bindings, or host configuration. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific g…

- **Type:** Skill
- **Install:** `agentstack add skill-managedcode-dotnet-skills-azure-functions`
- **Verified:** Pending review
- **Seller:** [managedcode](https://agentstack.voostack.com/s/managedcode)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [managedcode](https://github.com/managedcode)
- **Source:** https://github.com/managedcode/dotnet-skills/tree/main/catalog/Frameworks/Azure-Functions/skills/azure-functions
- **Website:** https://skills.managed-code.com

## Install

```sh
agentstack add skill-managedcode-dotnet-skills-azure-functions
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Azure Functions for .NET

## Trigger On

- working on Azure Functions in .NET
- migrating from the in-process model to the isolated worker model
- adding Durable Functions, bindings, or host configuration

## Documentation

- [Guide for running C# Azure Functions in an isolated worker process](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide)
- [Differences between in-process and isolated worker process](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-in-process-differences)
- [Migrate C# app from in-process to isolated worker model](https://learn.microsoft.com/en-us/azure/azure-functions/migrate-dotnet-to-isolated-model)
- [Durable Functions overview](https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview)
- [Durable Functions best practices and diagnostic tools](https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-best-practice-reference)

### References

- [Patterns](references/patterns.md) - Isolated worker patterns, Durable Functions patterns, advanced binding patterns
- [Anti-Patterns](references/anti-patterns.md) - Common Azure Functions mistakes and how to avoid them

## Workflow

1. **Use isolated worker model for all new work:**
   - In-process model reaches end of support on November 10, 2026
   - Runtime v1.x ends support on September 14, 2026
   - Target .NET 8+ for longest support window

2. **Detect current project shape:**
   - Target framework and runtime version
   - Worker model (isolated vs in-process)
   - Binding packages and host configuration

3. **Use standard .NET patterns in isolated model:**
   - Normal dependency injection
   - Middleware pipeline
   - `IOptions` for configuration
   - `ILogger` for logging

4. **For Durable Functions:**
   - Validate orchestration determinism constraints
   - Handle replay behavior correctly
   - Use typed activity patterns

5. **Verify both local and deployment behavior.**

## Isolated Worker Model Setup

### Basic Function with DI
```csharp
// Program.cs
var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddSingleton();
    })
    .Build();

host.Run();
```

### HTTP Trigger Function
```csharp
public class HttpFunctions(ILogger logger, IMyService myService)
{
    [Function("GetItems")]
    public async Task GetItems(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "items")] HttpRequest req)
    {
        logger.LogInformation("Processing GetItems request");
        var items = await myService.GetItemsAsync();
        return new OkObjectResult(items);
    }
}
```

### Queue Trigger with Options
```csharp
public class QueueFunctions(ILogger logger, IOptions options)
{
    [Function("ProcessMessage")]
    public async Task ProcessMessage(
        [QueueTrigger("myqueue", Connection = "AzureWebJobsStorage")] string message)
    {
        logger.LogInformation("Processing message: {Message}", message);
        // Process with retry policy from options
    }
}
```

## Middleware Pattern

### Custom Middleware
```csharp
// Program.cs
var host = new HostBuilder()
    .ConfigureFunctionsWebApplication(builder =>
    {
        builder.UseMiddleware();
        builder.UseMiddleware();
    })
    .Build();

// CorrelationIdMiddleware.cs
public class CorrelationIdMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var correlationId = context.Features.Get()?.Headers["X-Correlation-Id"]
            ?? Guid.NewGuid().ToString();

        context.Items["CorrelationId"] = correlationId;

        await next(context);
    }
}
```

## Durable Functions Patterns

### Function Chaining
```csharp
[Function(nameof(ChainOrchestrator))]
public static async Task ChainOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var result1 = await context.CallActivityAsync(nameof(Step1), "input");
    var result2 = await context.CallActivityAsync(nameof(Step2), result1);
    var result3 = await context.CallActivityAsync(nameof(Step3), result2);
    return result3;
}

[Function(nameof(Step1))]
public static string Step1([ActivityTrigger] string input) => $"Step1({input})";

[Function(nameof(Step2))]
public static string Step2([ActivityTrigger] string input) => $"Step2({input})";

[Function(nameof(Step3))]
public static string Step3([ActivityTrigger] string input) => $"Step3({input})";
```

### Fan-Out/Fan-In
```csharp
[Function(nameof(FanOutFanInOrchestrator))]
public static async Task FanOutFanInOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var workItems = await context.CallActivityAsync(nameof(GetWorkItems), null);

    // Fan out - process all items in parallel
    var tasks = workItems.Select(item =>
        context.CallActivityAsync(nameof(ProcessWorkItem), item));

    // Fan in - wait for all to complete
    var results = await Task.WhenAll(tasks);

    return results;
}

[Function(nameof(ProcessWorkItem))]
public static int ProcessWorkItem([ActivityTrigger] string item)
{
    // Process item and return result
    return item.Length;
}
```

### Human Interaction Pattern
```csharp
[Function(nameof(ApprovalOrchestrator))]
public static async Task ApprovalOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var request = context.GetInput();

    // Send notification
    await context.CallActivityAsync(nameof(SendApprovalRequest), request);

    // Wait for external event with timeout
    using var cts = new CancellationTokenSource();
    var approvalTask = context.WaitForExternalEvent("ApprovalEvent");
    var timeoutTask = context.CreateTimer(context.CurrentUtcDateTime.AddDays(7), cts.Token);

    var winner = await Task.WhenAny(approvalTask, timeoutTask);

    if (winner == approvalTask)
    {
        cts.Cancel();
        return approvalTask.Result ? "Approved" : "Rejected";
    }

    return "Timed out";
}
```

## Best Practices

1. **Use isolated worker model for new development** - Full .NET ecosystem access, middleware support, and longer support lifecycle
2. **Inject dependencies via constructor** - Use `ILogger` and service interfaces for testability
3. **Keep orchestrator code deterministic** - No I/O, random, DateTime.Now, or Guid.NewGuid() in orchestrators
4. **Handle sensitive data in activities** - Fetch secrets from Key Vault in activity functions, never in orchestrators
5. **Use unique task hub names** - Prevent accidental sharing when multiple apps use the same storage
6. **Avoid large inputs/outputs** - Serialize to blob storage for large payloads to prevent history bloat
7. **Configure concurrency limits** - Set appropriate limits in host.json for resource-intensive functions
8. **Keep SDK and extensions updated** - Latest versions include performance improvements and bug fixes

## Anti-Patterns to Avoid

| Anti-Pattern | Why It's Bad | Better Approach |
|--------------|--------------|-----------------|
| Mixing in-process and isolated guidance | Incompatible APIs and patterns | Choose one model consistently |
| Non-deterministic orchestrator code | Replay failures, stuck orchestrations | Use `context.CurrentUtcDateTime`, no I/O |
| Large orchestrator inputs/outputs | History bloat, memory issues | Store large data in blob storage |
| Shared task hub names | Message conflicts, stuck orchestrations | Use unique names per app |
| Secrets in orchestrator history | Security risk, exposed in logs | Fetch secrets in activity functions |
| Blocking calls in async functions | Thread pool exhaustion | Use `await` throughout |
| Missing retry policies | Transient failures cause job loss | Configure retry in bindings or code |
| Ignoring execution model migration | EOL November 2026 for in-process | Migrate to isolated worker model |

## Deployment Considerations

### Linux Consumption Plan Limitations
```
.NET 10+ apps cannot run on Linux Consumption plan.
Use Flex Consumption plan or App Service for .NET 10+.
.NET 9 is the last version supported on Linux Consumption.
```

### host.json Configuration
```json
{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "MyUniqueTaskHub",
      "maxConcurrentActivityFunctions": 10,
      "maxConcurrentOrchestratorFunctions": 5
    }
  },
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  }
}
```

## Deliver

- correct Functions project setup for the isolated worker model
- clear binding and host configuration
- middleware for cross-cutting concerns
- Durable Functions with proper orchestration patterns
- migration-safe guidance when upgrading execution models

## Validate

- execution model guidance is consistent (isolated only for new work)
- orchestrator code is deterministic
- bindings and host settings match the target runtime
- large payloads are externalized to blob storage
- retry policies are configured for transient failures
- local and deployment behavior are both verified

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [managedcode](https://github.com/managedcode)
- **Source:** [managedcode/dotnet-skills](https://github.com/managedcode/dotnet-skills)
- **License:** MIT
- **Homepage:** https://skills.managed-code.com

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** yes

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-managedcode-dotnet-skills-azure-functions
- Seller: https://agentstack.voostack.com/s/managedcode
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
