Start Debugging

Azure Functions modelo isolado vs in-process no .NET 11: qual escolher em 2026

Escolha o modelo isolated worker para toda nova aplicação Azure Functions no .NET 11 em 2026, e migre quaisquer aplicações in-process restantes antes do prazo de retirada de 10 de novembro.

Para qualquer nova aplicação Azure Functions em 2026, escolha o modelo isolated worker. É o único modelo que suporta .NET 9, .NET 10 e .NET 11. O modelo in-process se aposenta em 10 de novembro de 2026, o mesmo dia em que o .NET 8 LTS sai de suporte, e após essa data o Azure se recusará a hospedar funções in-process. Se você ainda tem uma aplicação in-process no .NET 6 ou .NET 8, a pergunta não é “qual modelo eu deveria escolher” mas “quão rápido eu consigo migrar”. Este post explica as diferenças, mostra os detalhes traiçoeiros e percorre o único eixo de decisão que ainda importa depois que ambos os runtimes desapareceram: como estruturar seu isolated worker para não abrir mão das coisas que o modelo in-process te dava de graça.

Este post mira o host v4 do Azure Functions, o modelo isolated worker do .NET sobre .NET 8 LTS até .NET 11 (preview no momento da escrita) e o modelo in-process sobre .NET 6 e .NET 8 LTS. Versões exatas de pacotes: Microsoft.Azure.Functions.Worker 2.0.x, Microsoft.Azure.Functions.Worker.Sdk 2.0.x, e para aplicações in-process Microsoft.NET.Sdk.Functions 4.5.x.

Os dois modelos, em um parágrafo cada

O modelo in-process carrega o assembly da sua função no mesmo processo do host do Azure Functions. O host é uma aplicação .NET mantida pela Microsoft, e está fixado a uma versão específica do runtime .NET. Seu código compartilha a versão do runtime do host, seu grafo de dependências e seu ciclo de vida. Os triggers e bindings que você declara com atributos como [BlobTrigger] mapeiam diretamente para as extensões WebJobs do host. Não há IPC entre seu código e o host porque eles são o mesmo processo.

O modelo isolated worker executa suas funções em um processo worker separado que você controla. O host o inicia, fala com ele por gRPC e encaminha os payloads dos triggers. Você traz seu próprio Program.cs, seu próprio HostBuilder, seu próprio container de injeção de dependência e, crucialmente, sua própria versão do runtime .NET. O host pode ficar em qualquer versão do .NET que a Microsoft envie; seu worker pode estar no .NET 11. Esse desacoplamento é exatamente o ponto: permite que a Microsoft pare de reconstruir o host para cada nova versão do .NET.

A matriz de recursos

RecursoIn-processIsolated worker
Última versão do .NET suportada.NET 8 LTS.NET 8, 9, 10, 11 (qualquer LTS ou STS atual)
Data de retirada10 de novembro de 2026ativo, sem retirada anunciada
Modelo de processocompartilhado com o hostprocesso worker separado
Comunicação com o hostem memóriagRPC sobre named pipes / TCP
Arquivo de inicializaçãoStartup.cs com FunctionsStartupProgram.cs com HostBuilder
Injeção de dependênciaDI do host, superfície de override limitadaMicrosoft.Extensions.DependencyInjection completo
Middlewarenão suportadosuportado via IFunctionsWorkerApplicationBuilder
Tipo de resposta HTTPIActionResult, HttpResponseMessageHttpResponseData, integração com ASP.NET Core (opt-in)
Logginginjeção de parâmetro ILoggerILogger via DI ou FunctionContext
Cobertura de triggers e bindingsmais ampla (toda extensão WebJobs)ampla, mas algumas extensões ainda ficam atrás
Cold start (função HTTP pequena, Linux)~250-400 ms no plano Consumption~350-600 ms no plano Consumption
Throughput em modo quenteligeiramente maior (sem IPC)ligeiramente menor (salto gRPC por invocação)
Tokens de cancelamento em funçõessuportados na maioria dos triggerssuportados em todos os triggers desde Worker 1.16
Suporte de OpenTelemetry de primeira classevia extensões do hostnativo via AddApplicationInsightsTelemetryWorkerService e exportadores OTel padrão
Compilação ahead-of-timenão suportadaNative AOT suportado em .NET 8+ para triggers HTTP

As duas linhas que decidem a escolha por você são as duas primeiras. Todo o resto é detalhe de implementação comparado a “o modelo está acabando em novembro de 2026”.

Quando escolher o modelo isolated worker

Para fins práticos, esta é agora a única escolha. Recorra a ele em cada um destes casos:

Um Program.cs mínimo do isolated worker se parece com isto:

// .NET 11, C# 14, Microsoft.Azure.Functions.Worker 2.0.x
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder.Services.AddHttpClient();
builder.Services.AddSingleton<IOrderStore, OrderStore>();

builder.UseMiddleware<CorrelationIdMiddleware>();

builder.Build().Run();

ConfigureFunctionsWebApplication() ativa a integração com ASP.NET Core para que seus triggers HTTP possam receber HttpRequest e retornar IActionResult, igualando o que os controllers fazem. Sem essa chamada, os triggers HTTP usam os tipos HttpRequestData / HttpResponseData do SDK do worker, que parecem mais verbosos mas são mais amigáveis ao Native AOT.

Quando escolher o modelo in-process

Resta exatamente um cenário: você tem uma aplicação in-process existente no .NET 6 ou .NET 8 que não consegue migrar antes de 10 de novembro de 2026, e precisa continuar lançando correções de bug contra ela até lá. Mantenha-a no .NET 8 LTS, não desperdice esforço afinando-a, e coloque a migração no roadmap.

Mais dois casos restritos que costumavam favorecer in-process, e como eles se parecem em 2026:

O benchmark de cold start

Abaixo estão os números que medi em um plano Linux Consumption na região West Europe. Metodologia: uma única função HTTP-triggered que retorna "hello". Cada linha é a mediana de 50 cold starts disparados após 25 minutos ociosos, usando azure-functions-perftools para conduzir o loop de curl. Mesmo host.json, mesma configuração de App Insights. .NET 8.0.18 LTS para as linhas in-process e isolated .NET 8; .NET 11.0 preview 4 para a linha .NET 11.

ConfiguraçãoCold start (p50)Cold start (p95)Latência em modo quente (p50)
In-process, .NET 8 LTS, JIT312 ms478 ms4,1 ms
Isolated worker, .NET 8 LTS, JIT488 ms702 ms6,8 ms
Isolated worker, .NET 11 preview 4, JIT451 ms661 ms6,2 ms
Isolated worker, .NET 8 LTS, Native AOT (apenas HTTP)198 ms287 ms3,4 ms
Isolated worker, .NET 11 preview 4, Native AOT (HTTP)181 ms266 ms3,1 ms

Duas coisas para ler nesta tabela. Primeiro, o isolated worker com JIT realmente é mais lento que o in-process em cold start, em cerca de 150 ms nesta carga. Esse gap é o handshake gRPC mais o processo worker subindo seu próprio HostBuilder. Segundo, Native AOT fecha o gap e mais um pouco: um isolated worker Native AOT é mais rápido do que o modelo in-process jamais foi. Se o seu caso de negócio para ficar in-process era cold start, a resposta moderna é mover-se para isolated e ligar AOT, não ficar onde está.

Os detalhes traiçoeiros que decidem por você

Duas coisas forçam a decisão independentemente da preferência.

A data de retirada é um prazo rígido, não uma recomendação. Em 10 de novembro de 2026, o Azure vai parar de aceitar implantações no modelo in-process e vai parar de escalar aplicações in-process existentes. A Microsoft publicou o aviso de retirada repetidamente desde o início de 2024, e em meados de 2026 a ferramenta de migração no dotnet upgrade-assistant cobre a maior parte dos passos mecânicos. Se sua função in-process é a porta de entrada de algo voltado ao cliente, “vamos migrar no Q1 2027” não é um plano, é uma indisponibilidade.

Alguns bindings têm comportamento sutilmente diferente nos dois modelos. Os dois mais prováveis de te morder durante uma migração:

Como a migração costuma ir

Uma migração típica de pequeno a médio porte de in-process para isolated worker em uma única function app .NET 8 leva um dia focado, mais uma janela de release. Os passos mecânicos:

  1. Mude a referência do SDK no .csproj de Microsoft.NET.Sdk.Functions para Microsoft.Azure.Functions.Worker.Sdk, e adicione Microsoft.Azure.Functions.Worker.
  2. Apague Startup.cs e FunctionsStartup. Substitua por um Program.cs que usa FunctionsApplication.CreateBuilder(args).
  3. Mude cada referência de extensão de binding de Microsoft.Azure.WebJobs.Extensions.* para Microsoft.Azure.Functions.Worker.Extensions.*.
  4. Reescreva as assinaturas das funções: parâmetros ILogger log se movem para injeção por construtor ou para FunctionContext.GetLogger<T>(). [FunctionName] vira [Function]. HttpRequest / IActionResult ou permanecem (se você chamar ConfigureFunctionsWebApplication()) ou mudam para HttpRequestData / HttpResponseData.
  5. Defina FUNCTIONS_WORKER_RUNTIME como dotnet-isolated na configuração da sua function app, e atualize o stack de runtime do slot de implantação no portal ou no Bicep.
  6. Execute a suíte de testes, depois implante em um slot de staging e rode um soak de 24 horas antes da troca.

dotnet upgrade-assistant automatiza os passos 1 a 4 para a maioria das aplicações. Os lugares onde ele não consegue ajudar são código equivalente a middleware customizado (que você geralmente quer converter em middleware real) e qualquer acesso baseado em reflection ao host WebJobs que não se aplica mais.

A recomendação opinativa, reafirmada

Use o modelo isolated worker para toda aplicação Azure Functions em 2026. Se você está começando do zero, faça scaffold no .NET 11 isolated e ligue Native AOT para triggers HTTP se cold start importar. Se você tem uma aplicação in-process, agende sua migração para aterrissar antes de outubro de 2026 para ter um mês de margem antes do prazo de retirada, e use esse mês para fazer soak do novo modelo sob tráfego real. O argumento “in-process é mais rápido” não é mais verdade uma vez que você adiciona AOT à comparação, e “in-process tem mais bindings” não é verdade desde a segunda metade de 2024.

Relacionado

Fontes

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Voltar