Azure Functions lets you run event-driven, serverless code in the cloud.
When using .NET, you can choose between two hosting models:

  1. In-Process Model – Functions run inside the Azure Functions runtime.

  2. Isolated Worker Model – Functions run in a separate .NET process, communicating with the host via gRPC.

With the release of .NET 9 , the Isolated Worker Model is the recommended and future-proof option.

1. In-Process Model

In this model, your functions run within the Azure Functions host process.

Example: In-Process Queue Trigger (C#, .NET 6)

using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;

public static class QueueExample
{
    [FunctionName("QueueExample")]
    public static void Run(
        [QueueTrigger("my-queue", Connection = "AzureWebJobsStorage")] string message,
        ILogger log)
    {
        log.LogInformation($"In-Process Function processed: {message}");
    }
}

Notice that there’s no Program.cs. Everything is handled by the runtime host.

2. Isolated Worker Model (Recommended with .NET 9)

In this model, your functions run in a separate .NET process.
This gives you full control over:

Example: HTTP Trigger with .NET 9 Isolated Worker

Project file: FunctionApp.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0-preview.6" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.0-preview.6" OutputItemType="Analyzer" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
  </ItemGroup>

</Project>

Program.cs

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var host = Host.CreateDefaultBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        services.AddSingleton<IMyService, MyService>();
    })
    .ConfigureLogging(logging =>
    {
        logging.AddConsole();
    })
    .Build();

host.Run();

public interface IMyService
{
    string GetMessage(string name);
}

public class MyService : IMyService
{
    public string GetMessage(string name) => $"Hello {name}, from a .NET 9 Isolated Function!";
}

HelloFunction.cs

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Net;

public class HelloFunction
{
    private readonly IMyService _service;
    private readonly ILogger<HelloFunction> _logger;

    public HelloFunction(IMyService service, ILogger<HelloFunction> logger)
    {
        _service = service;
        _logger = logger;
    }

    [Function("HelloFunction")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "hello/{name?}")] HttpRequestData req,
        string? name)
    {
        _logger.LogInformation("Processing request in .NET 9 isolated worker");

        var userName = string.IsNullOrEmpty(name) ? "World" : name;
        var response = req.CreateResponse(HttpStatusCode.OK);
        await response.WriteStringAsync(_service.GetMessage(userName));

        return response;
    }
}

Here, you own the startup pipeline (Program.cs), just like an ASP.NET Core app.

3. Key Differences

FeatureIn-Process ModelIsolated Worker Model (.NET 9)
RuntimeRuns inside Functions hostRuns in separate .NET process
.NET VersionsLimited by Functions runtime (up to .NET 6)Any modern .NET (7, 8, 9)
Startup CustomizationLimitedFull control with Program.cs
Dependency InjectionBuilt-inFully customizable
PerformanceSlightly faster cold startSlight gRPC overhead
Bindings SupportRicher (legacy + new)Some lagging support, but improving
Best Use CaseExisting/legacy appsNew apps, future-proof projects

Conclusion